0

I have this logon method:

   // POST: /Account/LogOn
    [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl, string corpid)
    {
      var sb = new StringBuilder();
      sb.AppendLine("Logon HttpPost start");
      sb.AppendLine(string.Format("returnUrl: {0}", returnUrl));
      sb.AppendLine(string.Format("corpid: {0}", corpid));
      sb.AppendLine(string.Format("model.UserName: {0}", model.UserName));
      sb.AppendLine(string.Format("model.Password: {0}", model.Password));

      try
      {
        sb.AppendLine(string.Format("ModelState.IsValid: {0}", ModelState.IsValid));
        if (ModelState.IsValid)
        {
          if (Membership.ValidateUser(model.UserName, model.Password))
          {
            sb.AppendLine("Validated User");
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1
                && returnUrl.StartsWith("/")
                && !returnUrl.StartsWith("//")
                && !returnUrl.StartsWith("/\\"))
            {
              sb.AppendLine("Redirect(returnUrl)");
              return Redirect(returnUrl);
            }

            // need to decide whether to display the CustomerSummary, AccountScreen, or AddCustomer view
            // AccountScreen if they only have 1 account tied to this logon
            // AddCustomer if they do not havfe any tied to this logon
            // CustomerSummary if they have more than 1 tied to this logon

            var customers = _client.RequestCustomersForAccount(model.UserName);
            if (!customers.Any())
            {
              // no accounts tied to this logon
              sb.AppendLine("No accounts found for this login.");
              sb.AppendLine("RedirectToAction(AddCustomer, Customer)");
              return RedirectToAction("AddCustomer", "Customer");
            }

            if (customers.Count() == 1)
            {
              sb.AppendLine("1 accounts found for this login.");
              sb.AppendLine("RedirectToAction(AccountScreen, Customer)");
              model.AccountId = customers[0].AccountId;
              sb.AppendLine(string.Format("customers[0].AccountId: {0}", customers[0].AccountId));
              // only 1 account tied to this logon
              return RedirectToAction("AccountScreen", "Customer", model);
            }

            if (customers.Count() > 1)
            {
              sb.AppendLine(string.Format("{0} accounts found for this login.", customers.Count()));
              sb.AppendLine("RedirectToAction(CustomerSummary, Customer)");
              // no accounts tied to this logon
              return RedirectToAction("CustomerSummary", "Customer");
            }

          }
          else
          {
            var msg = "The user name or password provided is incorrect.";
            sb.AppendLine(msg);
            ModelState.AddModelError("", msg);
          }
        }

        // If we got this far, something failed, redisplay form
        return View(model);

      }
      catch (Exception ex)
      {
        sb.AppendLine(string.Format("An error occured: {0}", ex));
        WebPortalLogging.Logging.LogException("The following error occured: ", ex, _asName);
        return null;
      }
      finally
      {
        WebPortalLogging.Logging.LogInfo(sb.ToString(), _asName);
      }
    }

When I get to line FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); I am getting this error:

System.InvalidOperationException: The username is not provided. Specify username in ClientCredentials.

Server stack trace: at System.ServiceModel.ClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement, Boolean disableInfoCard) at System.ServiceModel.Channels.HttpChannelFactory.CreateAndOpenTokenProvider(TimeSpan timeout, AuthenticationSchemes authenticationScheme, EndpointAddress target, Uri via, ChannelParameterCollection channelParameters) at System.ServiceModel.Channels.HttpChannelFactory.CreateAndOpenTokenProvidersCore(EndpointAddress to, Uri via, ChannelParameterCollection channelParameters, TimeSpan timeout, SecurityTokenProviderContainer& tokenProvider, SecurityTokenProviderContainer& proxyTokenProvider) at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.CreateAndOpenTokenProviders(TimeSpan timeout) at System.ServiceModel.Channels.HttpsChannelFactory.HttpsRequestChannel.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade) at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at SuburbanCustPortal.SuburbanService.ISuburbanService.RequestCustomersForAccount(String customerloginname) at SuburbanCustPortal.Controllers.AccountController.LogOn(LogOnModel model, String returnUrl, String corpid) in C:\work2\Doozer Software\Suburban\SuburbanCustPortal\Controllers\AccountController.cs:line 112

This code worked find at one time and I went back and compared it to what I had when it worked and I don't see anything other than the logging that has changed.

Here is the logging I added:

Logon HttpPost start
returnUrl: 
corpid: 
model.UserName: user
model.Password: password
ModelState.IsValid: True
Validated User
An error occured: System.InvalidOperationException: The username is not provided. Specify username in ClientCredentials.

Server stack trace: 
   at System.ServiceModel.ClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement, Boolean disableInfoCard)
   at System.ServiceModel.Channels.HttpChannelFactory.CreateAndOpenTokenProvider(TimeSpan timeout, AuthenticationSchemes authenticationScheme, EndpointAddress target, Uri via, ChannelParameterCollection channelParameters)
   at System.ServiceModel.Channels.HttpChannelFactory.CreateAndOpenTokenProvidersCore(EndpointAddress to, Uri via, ChannelParameterCollection channelParameters, TimeSpan timeout, SecurityTokenProviderContainer& tokenProvider, SecurityTokenProviderContainer& proxyTokenProvider)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.CreateAndOpenTokenProviders(TimeSpan timeout)
   at System.ServiceModel.Channels.HttpsChannelFactory.HttpsRequestChannel.OnOpen(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
   at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at SuburbanCustPortal.SuburbanService.ISuburbanService.RequestCustomersForAccount(String customerloginname)
   at SuburbanCustPortal.Controllers.AccountController.LogOn(LogOnModel model, String returnUrl, String corpid) in C:\work2\Doozer Software\Suburban\SuburbanCustPortal\Controllers\AccountController.cs:line 112

As you can see from the logs, I am logged in with a user since I pass this check:

 if (Membership.ValidateUser(model.UserName, model.Password))

Additionally, I can run this code locally, on my computer, and I get no error. This is all directed at the same database, locally and published.

Anyone see what my problem is?

ErocM
  • 4,505
  • 24
  • 94
  • 161

1 Answers1

0

When I get to line FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); I am getting this error:

Your stack trace shows that the exception is thrown by the line:

var customers = _client.RequestCustomersForAccount(model.UserName);

Presumably this call is failing because your Thread.CurrentPrincipal has not been set to the authenticated user (you set the FormsAuthentication cookie, but it won't be processed until the next request).

I'm not sure why you're trying to do additional work after authenticating the user, I suggest you redirect immediately, e.g.:

if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1
            && returnUrl.StartsWith("/")
            && !returnUrl.StartsWith("//")
            && !returnUrl.StartsWith("/\\"))
{
   sb.AppendLine("Redirect(returnUrl)");
   return Redirect(returnUrl);
}

Redirect(Request.UrlReferrer.ToString()); // Or wherever you want to redirect to
Joe
  • 122,218
  • 32
  • 205
  • 338
  • I am checking to see where to direct to after they have been authenticated. Pending on the number of accounts they have affects what page shows up next. – ErocM Nov 20 '12 at 21:31
  • You are right, the error is in the _client.RequestCustomersForAccount although it's due to it not receiving the credential for the service. – ErocM Nov 20 '12 at 21:50