title: Prevent ODP.net connetion from being open with expired password
body: <p>I'm working on a Silverlight application that uses oracle security to authenticate the users. (This is a business requirement so it can't be changed).</p>
  
  <p>I do so by calling a WCF web service that attempts to open a connection to the database using the provided username and password. If the connection fails, I catch the exception and return a message to the user, here's the login code:</p>
  
  <pre><code>[OperationContract]
  public LoginResult LogIn(string username, string password, DateTime preventCache)
  {
      var result = new List&lt;string&gt;();
  
      try
      {
         connectionString = ConfigurationManager.ConnectionStrings["SecurityBD"].ToString();
          connectionString = connectionString.Replace("[username]", username);
          connectionString = connectionString.Replace("[password]",passowrd)
          using (var connection = new Oracle.DataAccess.Client.OracleConnection())
          {
  
  
              connection.ConnectionString = connectionString;                    
              connection.Open();
              if (connection.State == System.Data.ConnectionState.Open)
              {                        
                  connection.Close();
                  return new LoginResult(true, GetPermisos(username), preventCache);
              }
              else
              {
                  return new LoginResult(false, null, preventCache);
              }
          }
  
      }
      catch (Oracle.DataAccess.Client.OracleException ex)
      {
          if (ex.Number == 1017)
          {
              return new LoginResult(new SecurityError("Wrong credentials.", ErrorType.InvalidCredentials));
          }
          //Password expired.
          if (ex.Number == 28001)
          {
              return new LoginResult(new SecurityError("Password expired.", ErrorType.PasswordExpired));
          }
          //Acount is locked.
          if (ex.Number == 28000)
          {
              return new LoginResult(new SecurityError("Account is locked.", ErrorType.AccountLocked));
          }
          else
          {
              return new LoginResult(new SecurityError("An error occurred while attempting to connect." + Environment.NewLine + "Error: " + ex.ToString(), ErrorType.UndefinedError));
          }
      }
      catch (Exception exg)
      {
          return new LoginResult(new SecurityError("An error occurred while attempting to connect." + Environment.NewLine + "Error: " + exg.ToString(), ErrorType.UndefinedError));
      }
  }
  </code></pre>
  
  <p>If the connection fails because of an expired password, I show the corresponding message to the user and then prompt him for his old and new password, and then send the new credentials to a ChangePassword method on my web serivce. </p>
  
  <pre><code>[OperationContract]      
  public ChangePasswordResult ChangePassword(string username, string oldPasswrod, string newPassword)
  {
      string connectionString = string.Empty;
      try
      {
                         connectionString = ConfigurationManager.ConnectionStrings["SecurityBD"].ToString();
          connectionString = connectionString.Replace("[username]", username);
          connectionString = connectionString.Replace("[password]",passowrd)
          using (var connection = new OracleConnection(connectionString))
          {                    
              connection.Open();
              if (connection.State == System.Data.ConnectionState.Open)
              {                        
                  connection.Close();
                  using (var newConnection = new Oracle.DataAccess.Client.OracleConnection(connectionString))
                  {
                      newConnection.OpenWithNewPassword(Cryptography.TransportDecrypt(newPassword));
                      if (newConnection.State == System.Data.ConnectionState.Open)
                      {
  
                          return new ChangePasswordResult(null);
                      }
                  }
              }
              return new ChangePasswordResult(new SecurityError("Couldn't connect to the database.", ErrorType.UndefinedError));
          }
      }
      catch (OracleException ex)
      {
          if (ex.Number == 1017)
          {
              return new ChangePasswordResult(new SecurityError("Wrong password", ErrorType.InvalidCredentials));
          }
          //Password expired.
          if (ex.Number == 28001)
          {
              using (var newConnection = new Oracle.DataAccess.Client.OracleConnection(connectionString))
              {
                  try
                  {
                      newConnection.OpenWithNewPassword(Cryptography.TransportDecrypt(newPassword));                            
                      if (newConnection.State == System.Data.ConnectionState.Open)
                      {
                          return new ChangePasswordResult(null);
                      }
                      else
                      {
                          return new ChangePasswordResult(new SecurityError("No se pudo establecer una conexión con la base de datos", ErrorType.UndefinedError));
                      }
                  }
                  catch (Oracle.DataAccess.Client.OracleException oex)
                  {
                      if (oex.Number == 28003)
                          return new ChangePasswordResult(new SecurityError("You'r new password does not match the security requeriments.." + Environment.NewLine + oex.Message, ErrorType.PasswordNotChanged));
                      else
                          return new ChangePasswordResult(new SecurityError(oex.Message, ErrorType.UndefinedError));
                  }
              }
          }
          //Acount is locked.
          if (ex.Number == 28000)
          {
              return new ChangePasswordResult(new SecurityError("Account is locked.", ErrorType.AccountLocked));
          }
          else
          {
              return new ChangePasswordResult(new SecurityError("Couldn't establish a connection." + Environment.NewLine + "Error: " + ex.Message, ErrorType.UndefinedError));
          }
      }
      catch
      {
          throw;
      }
  }
  </code></pre>
  
  <p>After I perform the change password operation, the user is still able to connect with the old password and he's not able to connect with the new password. Only after I restart the application the change seems to take effect.</p>
  
  <p>I'm using oracle's ODP.net driver. With Microsoft's oracle client, the user is able to connect with both the new  and the old password after the password change. </p>
  
  <p>The <code>preventCache</code> parameter was there only to verify that there was no type of client cache. I send the current date from the client, and then return the same value from the web service to see if it actually changes with subsequent requests, and it does as expected.</p>
  
  <p>I've tried listening to the <code>InfoMessage</code> event of the connection, to see if there's any warning, but doing this prevents the password expired exception from being risen, and the code never reaches the <code>eventHandler</code>.</p>
  
  <p>I'm completely lost, this behavior seems very odd to me and I still haven't figured out the root cause for the problem.</p>
  
  <p>I've tryied copying the <code>LogIn</code> and <code>ChangePassword</code> methods on a desktop (WPF) application and it behaves exactly the same. So i guess the problem is not in the silverlight client.</p>