@@ -119,7 +119,7 @@ sealed internal class SqlInternalConnectionTds : SqlInternalConnection, IDisposa
119
119
// Connection Resiliency
120
120
private bool _sessionRecoveryRequested ;
121
121
internal bool _sessionRecoveryAcknowledged ;
122
- internal SessionData _currentSessionData ; // internal for use from TdsParser only, otehr should use CurrentSessionData property that will fix database and language
122
+ internal SessionData _currentSessionData ; // internal for use from TdsParser only, other should use CurrentSessionData property that will fix database and language
123
123
private SessionData _recoverySessionData ;
124
124
125
125
// Federated Authentication
@@ -131,20 +131,33 @@ sealed internal class SqlInternalConnectionTds : SqlInternalConnection, IDisposa
131
131
internal bool _federatedAuthenticationInfoRequested ; // Keep this distinct from _federatedAuthenticationRequested, since some fedauth library types may not need more info
132
132
internal bool _federatedAuthenticationInfoReceived ;
133
133
134
+ // The Federated Authentication returned by TryGetFedAuthTokenLocked or GetFedAuthToken.
135
+ SqlFedAuthToken _fedAuthToken = null ;
134
136
internal byte [ ] _accessTokenInBytes ;
135
137
136
138
private readonly ActiveDirectoryAuthenticationTimeoutRetryHelper _activeDirectoryAuthTimeoutRetryHelper ;
137
139
private readonly SqlAuthenticationProviderManager _sqlAuthenticationProviderManager ;
138
140
139
141
// Certificate auth calbacks.
140
- //
141
142
ServerCertificateValidationCallback _serverCallback ;
142
143
ClientCertificateRetrievalCallback _clientCallback ;
143
144
SqlClientOriginalNetworkAddressInfo _originalNetworkAddressInfo ;
144
145
145
146
internal bool _cleanSQLDNSCaching = false ;
146
147
private bool _serverSupportsDNSCaching = false ;
147
148
149
+ /// <summary>
150
+ /// Returns buffer time allowed before access token expiry to continue using the access token.
151
+ /// </summary>
152
+ private int accessTokenExpirationBufferTime
153
+ {
154
+ get
155
+ {
156
+ return ( ConnectionOptions . ConnectTimeout == ADP . InfiniteConnectionTimeout || ConnectionOptions . ConnectTimeout >= ADP . MaxBufferAccessTokenExpiry )
157
+ ? ADP . MaxBufferAccessTokenExpiry : ConnectionOptions . ConnectTimeout ;
158
+ }
159
+ }
160
+
148
161
/// <summary>
149
162
/// Get or set if SQLDNSCaching FeatureExtAck is supported by the server.
150
163
/// </summary>
@@ -807,6 +820,10 @@ protected override bool UnbindOnTransactionCompletion
807
820
}
808
821
}
809
822
823
+ /// <summary>
824
+ /// Validates if federated authentication is used, Access Token used by this connection is active for the value of 'accessTokenExpirationBufferTime'.
825
+ /// </summary>
826
+ internal override bool IsAccessTokenExpired => _federatedAuthenticationInfoRequested && DateTime. FromFileTimeUtc( _fedAuthToken . expirationFileTime ) < DateTime . UtcNow. AddSeconds( accessTokenExpirationBufferTime ) ;
810
827
811
828
////////////////////////////////////////////////////////////////////////////////////////
812
829
// GENERAL METHODS
@@ -1320,10 +1337,10 @@ internal void ExecuteTransactionYukon(
1320
1337
ThreadHasParserLockForClose = false ;
1321
1338
_parserLock . Release ( ) ;
1322
1339
releaseConnectionLock = false ;
1323
- } , 0 ) ;
1340
+ } , ADP . InfiniteConnectionTimeout ) ;
1324
1341
if ( reconnectTask != null )
1325
1342
{
1326
- AsyncHelper . WaitForCompletion ( reconnectTask , 0 ) ; // there is no specific timeout for BeginTransaction, uses ConnectTimeout
1343
+ AsyncHelper . WaitForCompletion ( reconnectTask , ADP . InfiniteConnectionTimeout ) ; // there is no specific timeout for BeginTransaction, uses ConnectTimeout
1327
1344
internalTransaction . ConnectionHasBeenRestored = true ;
1328
1345
return ;
1329
1346
}
@@ -2537,9 +2554,6 @@ internal void OnFedAuthInfo(SqlFedAuthInfo fedAuthInfo)
2537
2554
// We want to refresh the token, if taking the lock on the authentication context is successful.
2538
2555
bool attemptRefreshTokenLocked = false ;
2539
2556
2540
- // The Federated Authentication returned by TryGetFedAuthTokenLocked or GetFedAuthToken.
2541
- SqlFedAuthToken fedAuthToken = null ;
2542
-
2543
2557
if ( _dbConnectionPool != null )
2544
2558
{
2545
2559
Debug . Assert ( _dbConnectionPool . AuthenticationContexts != null ) ;
@@ -2574,7 +2588,7 @@ internal void OnFedAuthInfo(SqlFedAuthInfo fedAuthInfo)
2574
2588
}
2575
2589
else if ( _forceExpiryLocked )
2576
2590
{
2577
- attemptRefreshTokenLocked = TryGetFedAuthTokenLocked ( fedAuthInfo , dbConnectionPoolAuthenticationContext , out fedAuthToken ) ;
2591
+ attemptRefreshTokenLocked = TryGetFedAuthTokenLocked ( fedAuthInfo , dbConnectionPoolAuthenticationContext , out _fedAuthToken ) ;
2578
2592
}
2579
2593
#endif
2580
2594
@@ -2588,11 +2602,11 @@ internal void OnFedAuthInfo(SqlFedAuthInfo fedAuthInfo)
2588
2602
2589
2603
// Call the function which tries to acquire a lock over the authentication context before trying to update.
2590
2604
// If the lock could not be obtained, it will return false, without attempting to fetch a new token.
2591
- attemptRefreshTokenLocked = TryGetFedAuthTokenLocked ( fedAuthInfo , dbConnectionPoolAuthenticationContext , out fedAuthToken ) ;
2605
+ attemptRefreshTokenLocked = TryGetFedAuthTokenLocked ( fedAuthInfo , dbConnectionPoolAuthenticationContext , out _fedAuthToken ) ;
2592
2606
2593
- // If TryGetFedAuthTokenLocked returns true, it means lock was obtained and fedAuthToken should not be null.
2607
+ // If TryGetFedAuthTokenLocked returns true, it means lock was obtained and _fedAuthToken should not be null.
2594
2608
// If there was an exception in retrieving the new token, TryGetFedAuthTokenLocked should have thrown, so we won't be here.
2595
- Debug . Assert ( ! attemptRefreshTokenLocked || fedAuthToken != null , "Either Lock should not have been obtained or fedAuthToken should not be null." ) ;
2609
+ Debug . Assert ( ! attemptRefreshTokenLocked || _fedAuthToken != null , "Either Lock should not have been obtained or _fedAuthToken should not be null." ) ;
2596
2610
Debug . Assert ( ! attemptRefreshTokenLocked || _newDbConnectionPoolAuthenticationContext != null , "Either Lock should not have been obtained or _newDbConnectionPoolAuthenticationContext should not be null." ) ;
2597
2611
2598
2612
// Indicate in Bid Trace that we are successful with the update.
@@ -2609,8 +2623,8 @@ internal void OnFedAuthInfo(SqlFedAuthInfo fedAuthInfo)
2609
2623
if ( dbConnectionPoolAuthenticationContext == null || attemptRefreshTokenUnLocked )
2610
2624
{
2611
2625
// Get the Federated Authentication Token.
2612
- fedAuthToken = GetFedAuthToken ( fedAuthInfo ) ;
2613
- Debug . Assert ( fedAuthToken != null , "fedAuthToken should not be null." ) ;
2626
+ _fedAuthToken = GetFedAuthToken ( fedAuthInfo ) ;
2627
+ Debug . Assert ( _fedAuthToken != null , "_fedAuthToken should not be null." ) ;
2614
2628
2615
2629
if ( _dbConnectionPool != null )
2616
2630
{
@@ -2621,18 +2635,19 @@ internal void OnFedAuthInfo(SqlFedAuthInfo fedAuthInfo)
2621
2635
else if ( ! attemptRefreshTokenLocked )
2622
2636
{
2623
2637
Debug . Assert ( dbConnectionPoolAuthenticationContext != null , "dbConnectionPoolAuthenticationContext should not be null." ) ;
2624
- Debug . Assert ( fedAuthToken == null , "fedAuthToken should be null in this case." ) ;
2638
+ Debug . Assert ( _fedAuthToken == null , "_fedAuthToken should be null in this case." ) ;
2625
2639
Debug . Assert ( _newDbConnectionPoolAuthenticationContext == null , "_newDbConnectionPoolAuthenticationContext should be null." ) ;
2626
2640
2627
- fedAuthToken = new SqlFedAuthToken ( ) ;
2641
+ _fedAuthToken = new SqlFedAuthToken ( ) ;
2628
2642
2629
2643
// If the code flow is here, then we are re-using the context from the cache for this connection attempt and not
2630
2644
// generating a new access token on this thread.
2631
- fedAuthToken . accessToken = dbConnectionPoolAuthenticationContext . AccessToken ;
2645
+ _fedAuthToken . accessToken = dbConnectionPoolAuthenticationContext . AccessToken ;
2646
+ _fedAuthToken . expirationFileTime = dbConnectionPoolAuthenticationContext . ExpirationTime . ToFileTime ( ) ;
2632
2647
}
2633
2648
2634
- Debug . Assert ( fedAuthToken != null && fedAuthToken . accessToken != null , "fedAuthToken and fedAuthToken .accessToken cannot be null." ) ;
2635
- _parser . SendFedAuthToken ( fedAuthToken ) ;
2649
+ Debug . Assert ( _fedAuthToken != null && _fedAuthToken . accessToken != null , "_fedAuthToken and _fedAuthToken .accessToken cannot be null." ) ;
2650
+ _parser . SendFedAuthToken ( _fedAuthToken ) ;
2636
2651
}
2637
2652
2638
2653
/// <summary>
@@ -2872,7 +2887,8 @@ internal void OnFeatureExtAck(int featureId, byte[] data)
2872
2887
{
2873
2888
if ( _routingInfo != null )
2874
2889
{
2875
- if ( TdsEnums . FEATUREEXT_SQLDNSCACHING != featureId ) {
2890
+ if ( TdsEnums . FEATUREEXT_SQLDNSCACHING != featureId )
2891
+ {
2876
2892
return ;
2877
2893
}
2878
2894
}
@@ -3100,16 +3116,18 @@ internal void OnFeatureExtAck(int featureId, byte[] data)
3100
3116
throw SQL . ParsingError ( ParsingErrorState . CorruptedTdsStream ) ;
3101
3117
}
3102
3118
3103
- if ( 1 == data [ 0 ] ) {
3119
+ if ( 1 == data [ 0 ] )
3120
+ {
3104
3121
IsSQLDNSCachingSupported = true ;
3105
3122
_cleanSQLDNSCaching = false ;
3106
-
3123
+
3107
3124
if ( _routingInfo != null )
3108
3125
{
3109
3126
IsDNSCachingBeforeRedirectSupported = true ;
3110
3127
}
3111
3128
}
3112
- else {
3129
+ else
3130
+ {
3113
3131
// we receive the IsSupported whose value is 0
3114
3132
IsSQLDNSCachingSupported = false ;
3115
3133
_cleanSQLDNSCaching = true ;
0 commit comments