@@ -2489,8 +2489,6 @@ internal bool TryGetFedAuthTokenLocked(SqlFedAuthInfo fedAuthInfo, DbConnectionP
24892489 /// <returns>SqlFedAuthToken</returns>
24902490 internal SqlFedAuthToken GetFedAuthToken ( SqlFedAuthInfo fedAuthInfo )
24912491 {
2492- Debug . Assert ( fedAuthInfo != null , "fedAuthInfo should not be null." ) ;
2493-
24942492 // Number of milliseconds to sleep for the initial back off, if a
24952493 // retry period is not specified by the provider.
24962494 const int defaultRetryPeriod = 100 ;
@@ -2509,7 +2507,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
25092507
25102508 // We will perform retries if the provider indicates an error that
25112509 // is retryable.
2512- for ( int retryAttempt = 0 ; retryAttempt < maxRetryAttempts ; ++ retryAttempt )
2510+ for ( int retryAttempt = 0 ; retryAttempt <= maxRetryAttempts ; ++ retryAttempt )
25132511 {
25142512 try
25152513 {
@@ -2566,9 +2564,9 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
25662564 _activeDirectoryAuthTimeoutRetryHelper . CachedToken = _fedAuthToken ;
25672565 }
25682566 break ;
2569- #pragma warning disable 0618 // Type or member is obsolete
2567+ #pragma warning disable 0618 // Type or member is obsolete
25702568 case SqlAuthenticationMethod . ActiveDirectoryPassword :
2571- #pragma warning restore 0618 // Type or member is obsolete
2569+ #pragma warning restore 0618 // Type or member is obsolete
25722570 case SqlAuthenticationMethod . ActiveDirectoryServicePrincipal :
25732571 if ( _activeDirectoryAuthTimeoutRetryHelper . State == ActiveDirectoryAuthenticationTimeoutRetryState . Retrying )
25742572 {
@@ -2633,17 +2631,15 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
26332631 }
26342632 catch ( SqlAuthenticationProviderException ex )
26352633 {
2636- // We use a doubling backoff if the provider didn't provide
2637- // a retry period.
2638- int retryPeriod = defaultRetryPeriod * ( 2 ^ retryAttempt ) ;
2639-
2640- // Should we retry, and were we given a useful retry period?
2641- if ( ex . ShouldRetry && ex . RetryPeriod > 0 )
2634+ // Is the error fatal or retryable?
2635+ if ( ! ex . ShouldRetry )
26422636 {
2643- // Yes , so use it .
2644- retryPeriod = ex . RetryPeriod ;
2637+ // It's fatal , so translate into a SqlException .
2638+ throw ADP . CreateSqlException ( ex , ConnectionOptions , this , username ) ;
26452639 }
26462640
2641+ // We should retry.
2642+
26472643 // Could we retry if we wanted to?
26482644 if ( _timeout . IsExpired || _timeout . MillisecondsRemaining <= 0 )
26492645 {
@@ -2652,26 +2648,37 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
26522648 throw SQL . ActiveDirectoryTokenRetrievingTimeout ( Enum . GetName ( typeof ( SqlAuthenticationMethod ) , ConnectionOptions . Authentication ) , ex . FailureCode , ex ) ;
26532649 }
26542650
2655- // We will retry, so log.
2651+ // We use a doubling backoff if the provider didn't provide
2652+ // a retry period.
2653+ int retryPeriod =
2654+ ex . RetryPeriod > 0
2655+ ? ex . RetryPeriod
2656+ : defaultRetryPeriod * ( 2 ^ retryAttempt ) ;
2657+
26562658 SqlClientEventSource . Log . TryAdvancedTraceEvent ( "<sc.SqlInternalConnectionTds.GetFedAuthToken|ADV> {0}, Retry Attempt: {1}, sleeping {2}[Milliseconds]" , ObjectID , retryAttempt , retryPeriod ) ;
26572659 SqlClientEventSource . Log . TryAdvancedTraceEvent ( "<sc.SqlInternalConnectionTds.GetFedAuthToken|ADV> {0}, Retry Attempt: {1}, remaining {2}[Milliseconds]" , ObjectID , retryAttempt , _timeout . MillisecondsRemaining ) ;
26582660
26592661 // Sleep for the desired period.
26602662 Thread . Sleep ( retryPeriod ) ;
2663+
2664+ // Fall through to retry...
26612665 }
26622666 }
26632667
2664- // if (_fedAuthToken is null)
2665- // {
2666- // // TODO: This is a logic error - eliminate it.
2667- // throw SqlException.CreateException(
2668- // new SqlErrorCollection().Add(
2669- // new SqlError(
2670- // 0, (byte)0, (byte)0, "unknown",
2671- // "Logic error; fedAuthToken is null",
2672- // null, 0)),
2673- // "unknown", this, null, null);
2674- // }
2668+ // Nullable context has exposed that _fedAuthToken may be null here,
2669+ // which the existing code didn't handle.
2670+ if ( _fedAuthToken is null )
2671+ {
2672+ // We failed to acquire a token, so use a default one.
2673+ //
2674+ // TODO: The old code actually allowed the AccessToken byte
2675+ // array to be null, and then had Debug.Assert()s to verify it
2676+ // wasn't null. We never test in debug, so those were never
2677+ // firing, and we were happily using a _fedAuthToken with a null
2678+ // AccessToken. Now that SqlFedAuthToken doesn't allow a null
2679+ // AccessToken, we just create an empty one instead.
2680+ _fedAuthToken = new SqlFedAuthToken ( [ ] , 0 ) ;
2681+ }
26752682
26762683 // Store the newly generated token in _newDbConnectionPoolAuthenticationContext, only if using pooling.
26772684 if ( _dbConnectionPool != null )
0 commit comments