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

[BUG] Transactions may be lost due to an unhandled SqlException when accessing claims #2181

Closed
stevejgordon opened this issue Sep 12, 2023 · 0 comments · Fixed by #2182
Closed
Assignees
Labels
agent-dotnet bug Something isn't working

Comments

@stevejgordon
Copy link
Contributor

When instrumenting ASP.NET Full Framework, we attempt to access user information from the HttpContext to populate the transaction.Context.User. We go further and when possible, attempt to extract the email and ID from ClaimsPrinciple.Claims.

Depending on the application configuration, user and role information may be stored in SQL Server. In that case, the SqlRoleProvider will attempt to access the roles from the database. If the current application user does not have permission to access the database, then a SqlException, with the message "Login failed for user 'DOMAIN\username', will be thrown.

Our current implementation does not handle this exception, and if thrown, this bubbles up to the code in ProcessEndRequest which causes transaction.End() never to be called.

We should handle this exception such that it doesn't prevent the transaction from being ended.

Example stack trace when this occurs:

{ElasticApmModule.#1} Processing EndRequest event failed+-> Exception: System.Data.SqlClient.SqlException: Login failed for user 'DOMAIN\username'.
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken, Boolean applyTransientFaultHandling, SqlAuthenticationProviderManager sqlAuthProviderManager)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at System.Web.DataAccess.SqlConnectionHolder.Open(HttpContext context, Boolean revertImpersonate)
   at System.Web.DataAccess.SqlConnectionHelper.GetConnection(String connectionString, Boolean revertImpersonation)
   at System.Web.Security.SqlRoleProvider.GetRolesForUser(String username)
   at System.Web.Security.RolePrincipal.GetRoles()
   at System.Web.Security.RoleClaimProvider.<get_Claims>d__4.MoveNext()
   at System.Security.Claims.ClaimsIdentity.<get_Claims>d__51.MoveNext()
   at System.Security.Claims.ClaimsPrincipal.<get_Claims>d__37.MoveNext()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at Elastic.Apm.AspNetFullFramework.ElasticApmModule.<FillSampledTransactionContextUser>g__GetClaimWithFallbackValue|25_0(ClaimsPrincipal principal, String claimType, String fallbackClaimType)
   at Elastic.Apm.AspNetFullFramework.ElasticApmModule.FillSampledTransactionContextUser(HttpContext context, ITransaction transaction)
   at Elastic.Apm.AspNetFullFramework.ElasticApmModule.ProcessEndRequest(Object sender)
   at Elastic.Apm.AspNetFullFramework.ElasticApmModule.OnEndRequest(Object sender, EventArgs e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
agent-dotnet bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant