Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Hotfix 4.0.2] | Handle NRE on Azure federated authentication (#1625) #1722

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ public void AssertUnrecoverableStateCountIsCorrect()

internal sealed class SqlInternalConnectionTds : SqlInternalConnection, IDisposable
{
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/retry-after#simple-retry-for-errors-with-http-error-codes-500-600
internal const int MsalHttpRetryStatusCode = 429;

// CONNECTION AND STATE VARIABLES
private readonly SqlConnectionPoolGroupProviderInfo _poolGroupProviderInfo; // will only be null when called for ChangePassword, or creating SSE User Instance
private TdsParser _parser;
Expand Down Expand Up @@ -2421,7 +2424,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
// Deal with Msal service exceptions first, retry if 429 received.
catch (MsalServiceException serviceException)
{
if (429 == serviceException.StatusCode)
if (serviceException.StatusCode == MsalHttpRetryStatusCode)
{
RetryConditionHeaderValue retryAfter = serviceException.Headers.RetryAfter;
if (retryAfter.Delta.HasValue)
Expand All @@ -2440,9 +2443,15 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
}
else
{
break;
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.GetFedAuthToken.MsalServiceException error:> Timeout: {0}", serviceException.ErrorCode);
throw SQL.ActiveDirectoryTokenRetrievingTimeout(Enum.GetName(typeof(SqlAuthenticationMethod), ConnectionOptions.Authentication), serviceException.ErrorCode, serviceException);
}
}
else
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.GetFedAuthToken.MsalServiceException error:> {0}", serviceException.ErrorCode);
throw ADP.CreateSqlException(serviceException, ConnectionOptions, this, username);
}
}
// Deal with normal MsalExceptions.
catch (MsalException msalException)
Expand All @@ -2453,21 +2462,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.GetFedAuthToken.MSALException error:> {0}", msalException.ErrorCode);

// Error[0]
SqlErrorCollection sqlErs = new();
sqlErs.Add(new SqlError(0, (byte)0x00, (byte)TdsEnums.MIN_ERROR_CLASS, ConnectionOptions.DataSource, StringsHelper.GetString(Strings.SQL_MSALFailure, username, ConnectionOptions.Authentication.ToString("G")), ActiveDirectoryAuthentication.MSALGetAccessTokenFunctionName, 0));

// Error[1]
string errorMessage1 = StringsHelper.GetString(Strings.SQL_MSALInnerException, msalException.ErrorCode);
sqlErs.Add(new SqlError(0, (byte)0x00, (byte)TdsEnums.MIN_ERROR_CLASS, ConnectionOptions.DataSource, errorMessage1, ActiveDirectoryAuthentication.MSALGetAccessTokenFunctionName, 0));

// Error[2]
if (!string.IsNullOrEmpty(msalException.Message))
{
sqlErs.Add(new SqlError(0, (byte)0x00, (byte)TdsEnums.MIN_ERROR_CLASS, ConnectionOptions.DataSource, msalException.Message, ActiveDirectoryAuthentication.MSALGetAccessTokenFunctionName, 0));
}
SqlException exc = SqlException.CreateException(sqlErs, "", this);
throw exc;
throw ADP.CreateSqlException(msalException, ConnectionOptions, this, username);
}

SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.GetFedAuthToken|ADV> {0}, sleeping {1}[Milliseconds]", ObjectID, sleepInterval);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,10 @@ internal static Exception ActiveDirectoryDeviceFlowTimeout()
return ADP.TimeoutException(Strings.SQL_Timeout_Active_Directory_DeviceFlow_Authentication);
}

internal static Exception ActiveDirectoryTokenRetrievingTimeout(string authenticaton, string errorCode, Exception exception)
{
return ADP.TimeoutException(StringsHelper.GetString(Strings.AAD_Token_Retrieving_Timeout, authenticaton, errorCode, exception?.Message), exception);
}

//
// SQL.DataCommand
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1932,4 +1932,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>Parameter '{0}' cannot have Direction Output or InputOutput when EnableOptimizedParameterBinding is enabled on the parent command.</value>
</data>
</root>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>Connection timed out while retrieving an access token using '{0}' authentication method. Last error: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ public void AssertUnrecoverableStateCountIsCorrect()

sealed internal class SqlInternalConnectionTds : SqlInternalConnection, IDisposable
{
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/retry-after#simple-retry-for-errors-with-http-error-codes-500-600
internal const int MsalHttpRetryStatusCode = 429;

// Connection re-route limit
internal const int _maxNumberOfRedirectRoute = 10;
Expand Down Expand Up @@ -2859,7 +2861,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
// Deal with Msal service exceptions first, retry if 429 received.
catch (MsalServiceException serviceException)
{
if (429 == serviceException.StatusCode)
if (serviceException.StatusCode == MsalHttpRetryStatusCode)
{
RetryConditionHeaderValue retryAfter = serviceException.Headers.RetryAfter;
if (retryAfter.Delta.HasValue)
Expand All @@ -2878,9 +2880,15 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
}
else
{
break;
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.GetFedAuthToken.MsalServiceException error:> Timeout: {0}", serviceException.ErrorCode);
throw SQL.ActiveDirectoryTokenRetrievingTimeout(Enum.GetName(typeof(SqlAuthenticationMethod), ConnectionOptions.Authentication), serviceException.ErrorCode, serviceException);
}
}
else
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.GetFedAuthToken.MsalServiceException error:> {0}", serviceException.ErrorCode);
throw ADP.CreateSqlException(serviceException, ConnectionOptions, this, username);
}
}
// Deal with normal MsalExceptions.
catch (MsalException msalException)
Expand All @@ -2891,21 +2899,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.GetFedAuthToken.MSALException error:> {0}", msalException.ErrorCode);

// Error[0]
SqlErrorCollection sqlErs = new SqlErrorCollection();
sqlErs.Add(new SqlError(0, (byte)0x00, (byte)TdsEnums.MIN_ERROR_CLASS, ConnectionOptions.DataSource, StringsHelper.GetString(Strings.SQL_MSALFailure, username, ConnectionOptions.Authentication.ToString("G")), ActiveDirectoryAuthentication.MSALGetAccessTokenFunctionName, 0));

// Error[1]
string errorMessage1 = StringsHelper.GetString(Strings.SQL_MSALInnerException, msalException.ErrorCode);
sqlErs.Add(new SqlError(0, (byte)0x00, (byte)TdsEnums.MIN_ERROR_CLASS, ConnectionOptions.DataSource, errorMessage1, ActiveDirectoryAuthentication.MSALGetAccessTokenFunctionName, 0));

// Error[2]
if (!string.IsNullOrEmpty(msalException.Message))
{
sqlErs.Add(new SqlError(0, (byte)0x00, (byte)TdsEnums.MIN_ERROR_CLASS, ConnectionOptions.DataSource, msalException.Message, ActiveDirectoryAuthentication.MSALGetAccessTokenFunctionName, 0));
}
SqlException exc = SqlException.CreateException(sqlErs, "", this);
throw exc;
throw ADP.CreateSqlException(msalException, ConnectionOptions, this, username);
}

SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.GetFedAuthToken|ADV> {0}, sleeping {1}[Milliseconds]", ObjectID, sleepInterval);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,11 @@ static internal Exception ActiveDirectoryDeviceFlowTimeout()
return ADP.TimeoutException(Strings.SQL_Timeout_Active_Directory_DeviceFlow_Authentication);
}

internal static Exception ActiveDirectoryTokenRetrievingTimeout(string authenticaton, string errorCode, Exception exception)
{
return ADP.TimeoutException(StringsHelper.GetString(Strings.AAD_Token_Retrieving_Timeout, authenticaton, errorCode, exception?.Message), exception);
}

//
// SQL.DataCommand
//
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>Der Parameter "{0}" kann keine Ausgaberichtung oder InputOutput aufweisen, wenn EnableOptimizedParameterBinding für den übergeordneten Befehl aktiviert ist.</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>Timeout bei der Verbindung beim Abrufen eines Zugriffstokens mithilfe der Authentifizierungsmethode "{0}". Letzter Fehler: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>El parámetro “{0}” no puede tener la Dirección de salida ni InputOutput cuando EnableOptimizedParameterBinding está habilitado en el comando primario.</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>Se agotó el tiempo de espera de la conexión al recuperar un token de acceso mediante el método de autenticación "{0}". Último error: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>Le paramètre « {0} » ne peut pas avoir Direction Output ou InputOutput lorsque EnableOptimizedParameterBinding est activé sur la commande parente.</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>La connexion a expiré lors de la récupération d’un jeton d’accès à l’aide de '{0}' méthode d’authentification. Dernière erreur : {1} : {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>Il parametro '{0}' non può includere Output o InputOutput come valore di Direction quando nel comando padre è abilitato EnableOptimizedParameterBinding.</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>Timeout della connessione durante il recupero di un token di accesso tramite il metodo di autenticazione '{0}'. Ultimo errore: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>親コマンドで EnableOptimizedParameterBinding が有効になっている場合、パラメーター '{0}' に Direction 出力または InputOutput は指定できません。</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>認証方法 '{0}' によるアクセス トークンの取得中に接続がタイムアウトしました。前回のエラー: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>부모 명령에서 EnableOptimizedParameterBinding을 사용하는 경우 매개 변수 '{0}'에는 Direction Output 또는 InputOutput을 사용할 수 없습니다.</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>'{0}' 인증 방법을 사용하여 액세스 토큰을 검색하는 동안 연결 시간이 초과되었습니다. 마지막 오류: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>O parâmetro '{0}' não pode ter a saída de direção ou InputOutput quando EnableOptimizedParameterBinding está habilitado no comando pai.</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>A conexão expirou ao recuperar um token de acesso usando o método de autenticação '{0}'. Último erro: {1}: {2}</value>
</data>
</root>
3 changes: 3 additions & 0 deletions src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>Parameter '{0}' cannot have Direction Output or InputOutput when EnableOptimizedParameterBinding is enabled on the parent command.</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>Connection timed out while retrieving an access token using '{0}' authentication method. Last error: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>У параметра "{0}" не может быть направления вывода или InputOutput, если EnableOptimizedParameterBinding включен в родительской команде.</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>Истекло время ожидания подключения при получении маркера доступа с помощью метода проверки подлинности "{0}". Последняя ошибка: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>当在父命令上启用 EnableOptimizedParameterBinding 时,参数“{0}”不能具有 Direction Output 或 InputOutput。</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>使用“{0}”身份验证方法检索访问令牌时连接超时。最后一个错误: {1}: {2}</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4617,4 +4617,7 @@
<data name="SQL_ParameterDirectionInvalidForOptimizedBinding" xml:space="preserve">
<value>在父命令上啟用 EnableOptimizedParameterBinding 時,參數 '{0}' 不能具有方向輸出或 InputOutput。</value>
</data>
<data name="AAD_Token_Retrieving_Timeout" xml:space="preserve">
<value>使用 '{0}' 驗證方法擷取存取權杖時已逾時。上次錯誤: {1}: {2}</value>
</data>
</root>
Loading