title: MailChimp oauth2 in ASP.NET keeps returning invalid_grant
body: <p>I am developing a new app that offers integration with MailChimp. Basically, it enables users to easily export their customer contact info directly to a MailChimp account (that is, to a specific mailing-list inside MailChimp).
  All that works, and are somewhat irrelevant to my question.</p>
  
  <p>For not asking the user to enter MailChimp-credentials every time, I'm about to implement the oauth2 authorization workflow as described here: <a href="http://apidocs.mailchimp.com/oauth2/" rel="nofollow noreferrer">http://apidocs.mailchimp.com/oauth2/</a></p>
  
  <p>It works just fine in step 1-3, but step 4 is killing me.
  It's my first time working with oauth, but I seem to understand the basics.</p>
  
  <p><strong>Here is my problem:</strong></p>
  
  <p>When I do the POST call to the <a href="https://login.mailchimp.com/oauth2/token" rel="nofollow noreferrer">https://login.mailchimp.com/oauth2/token</a> -URI, to get the final access-token, I keep getting the error in JSON result: <strong>"invalid_grant"</strong></p>
  
  <p>I have checked the request and response streams, that my url is compiled correctly.</p>
  
  <p>Here is my code in the controller:</p>
  
  <p>(GrantEcoAccess is just to grant access to another app - the rest should be self-explaining)</p>
  
  <pre><code>public class HomeController : ApplicationController
  {
  
      private readonly string authorize_uri = "https://login.mailchimp.com/oauth2/authorize";
      private readonly string access_token_uri = "https://login.mailchimp.com/oauth2/token";
      private readonly string mailchimp_clientid2 = "xxx";
      private readonly string mailchimp_secret2 = "yyy";
  
      ...
  
      public ActionResult GrantEcoAccess()
      {
  
          //if exist: use saved token
          var user = (Mailchimp_users)Session["user"];
          if (!string.IsNullOrWhiteSpace(user.EcoToken))
              return RedirectToAction("GrantMailChimpAccess");
  
          // if !
          var url = "https://secure.e-conomic.com/secure/api1/requestaccess.aspx?role=superuser&amp;appId=MailChimp&amp;redirectUrl=http://localhost:18017/Home/IncomingToken";
          Redirect(url).ExecuteResult(ControllerContext);
          return null;
      }
  
  
      public ActionResult IncomingToken(string token)
      {
          var user = (Mailchimp_users)Session["user"];
          user.EcoToken = token;
          EcoSession.DataSession.Refresh(System.Data.Objects.RefreshMode.ClientWins, user);
          EcoSession.DataSession.SaveChanges();
  
          return RedirectToAction("GrantMailChimpAccess");
      }
  
      public ActionResult GrantMailChimpAccess()
      {
  
          //if exist: use saved token
          var user = (Mailchimp_users)Session["user"];
          if (!string.IsNullOrWhiteSpace(user.MailChimpToken))
              return RedirectToAction("Index", "Subscribe");
  
  
  
          //if !
          var url = string.Format("{0}?response_type=code&amp;client_id={1}&amp;redirect_uri=", authorize_uri, mailchimp_clientid2, "http://127.0.0.1:18017/Home/IncomingMailChimpToken");
          Redirect(url).ExecuteResult(ControllerContext);
          return null;
      }
  
      public ActionResult IncomingMailChimpToken(string code)
      {
  
  
          var url = "https://login.mailchimp.com/oauth2/token?grant_type=authorization_code&amp;client_id=XX&amp;client_secret=XX&amp;code=" + code + "&amp;redirect_uri=http://127.0.0.1:18017/Home/AuthComplete";
          //var url = string.Format("?grant_type=authorization_code&amp;client_id={0}&amp;client_secret={1}&amp;code={2}&amp;redirect_uri={3}", mailchimp_clientid, mailchimp_secret, code, Url.Action("AuthComplete"));
  
  
          Response.Clear();
  
          StringBuilder sb = new StringBuilder();
          sb.Append("&lt;html&gt;");
          sb.AppendFormat(@"&lt;body onload='document.forms[""form""].submit()'&gt;");
          sb.AppendFormat("&lt;form name='form' action='{0}' method='post'&gt;", access_token_uri);
  
          sb.Append("&lt;input type='hidden' name='grant_type' value='authorization_code'&gt;");
          sb.AppendFormat("&lt;input type='hidden' name='client_id' value='{0}'&gt;", mailchimp_clientid2);
          sb.AppendFormat("&lt;input type='hidden' name='client_secret' value='{0}'&gt;", mailchimp_secret2);
          sb.AppendFormat("&lt;input type='hidden' name='code' value='{0}'&gt;", code);
          sb.AppendFormat("&lt;input type='hidden' name='redirect_uri' value='{0}'&gt;", "http://127.0.0.1:18017/Home/AuthComplete");
          // Other params go here
  
          sb.Append("&lt;/form&gt;");
          sb.Append("&lt;/body&gt;");
          sb.Append("&lt;/html&gt;");
  
          Response.Write(sb.ToString());
          Response.End();
  
          return null;
  
      }
  
      public ActionResult AuthComplete(string access_token, string expires_in, string scope)
      {
          if (string.IsNullOrWhiteSpace(access_token))
              throw new Exception("Could not authorize user with MailChimp");
  
          var user = (Mailchimp_users)Session["user"];
          user.MailChimpToken = access_token;
          EcoSession.DataSession.Refresh(System.Data.Objects.RefreshMode.ClientWins, user);
          EcoSession.DataSession.SaveChanges();
  
  
          return RedirectToAction("Index", "Subscribe");
      }
  
  }
  </code></pre>
  
  <p>It is step 4 that is killing me, not step 5.</p>