title: How to invalidate a C# WCF session if login is incorrect
body: <p>I am writing a remote service for an application using WCF, in which login information is kept in a database. The service requires session establishment through a login or account creation call. There is no ASP involved.</p>
  
  <p>Now, when a client starts a session by calling an exposed <em>IsInitiating</em> method, I check the account data provided against the information on the database and, if it is not correct, I want to invalidate that session and force the client to start again with a call to an <em>IsInitiating</em> method.</p>
  
  <p>Looking at <a href="https://stackoverflow.com/questions/2763384/wcf-simple-login">some</a> <a href="https://stackoverflow.com/questions/100053/wcf-overhead-of-throwing-faultexceptions-within-your-service">other</a> questions, I have found pros and cons for two ways to invalidate a session. One does so the hard way, by throwing a FaultException; the other with softer manners, storing accepted session IDs.</p>
  
  <p>Now, the first one, although achieving what I desire, is way too aggressive, given that incorrect logins are part of the normal flow of the application. The second one, on the other hand, allows the client to continue calling non-initiating methods, eventhough they will be rejected, while also incurring in a considerable code overhead on the service due to the added thread safety requirements.</p>
  
  <p>So, the question: Is there a third path which allows the service to invalidate the session initialization and communicate it to the client, so it is forced to make a new <em>IsInitiating</em> call?</p>
  
  <p>A reduced version of the code I have:</p>
  
  <pre><code>[DataContractAttribute]
  public class AccountLoginFault
  {
      public AccountLoginFault (string message)
      {
          this.Message = message;
      }
  
      [DataMemberAttribute]
      public string Message { get; set; }
  }
  
  [ServiceContract (SessionMode = SessionMode.Required)]
  public interface IAccountService
  {
      [OperationContract (
          IsInitiating = true)]
      [FaultContractAttribute (
          typeof (AccountLoginFault),
          ProtectionLevel = ProtectionLevel.EncryptAndSign)]
      bool Login (AccountData account, out string message);
  }
  
  [ServiceBehavior (
      ConcurrencyMode = ConcurrencyMode.Single,
      InstanceContextMode = InstanceContextMode.PerSession)]
  public class AccountService : IAccountService
  {
      public bool Login (AccountData account, out string message)
      {
          UserManager userdb = ChessServerDB.UserManager;
          bool result = false;
          message = String.Empty;
  
          UserData userData = userdb.GetUserData (account.Name);
  
          if (userData.Name.Equals (account.Name)
              &amp;&amp; userData.Password.Equals (account.Password))
          {
              // Option one
              // Get lock
              // this.AcceptedSessions.Add (session.ID);
              // Release lock
  
              result = true;
          } else
          {
              result = false;
  
              // Option two
              // Do something with session context to mark it as not properly initialized.
              // message = "Incorrect account name or password. Account provided was " + account.Name;
  
              // Option three
              throw new FaultException&lt;AccountLoginFault&gt; (
                  new AccountLoginFault (
                      "Incorrect account name or password. Account provided was " + account.Name));
          }
  
          return result;
      }
  }
  </code></pre>