mailchimp oauth2 in ASP.NET keep returning invalid_grant

这一生的挚爱 提交于 2019-12-02 03:27:33

问题


I am developing a new app at work, 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.

For not asking the user to enter MailChimp-credentials every time, I'm about to implement the oauth2 authorization workflow as described here: http://apidocs.mailchimp.com/oauth2/

It works just fine in step 1-3, but step 4 is killing me.. Its my first time working with oauth, but I seem to understand the basics.

Here my problem:

When I do the POST call to the https://login.mailchimp.com/oauth2/token -URI, to get the final access-token, I keep getting the error in JSON result: "invalid_grant"

I have checked the request and response streams, that my url is compiled correctly.

Here is my code in the controller:

(GrantEcoAccess is just to grant access to another app - the rest should be self-explaining)

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 = "xxx

    ...

    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&appId=MailChimp&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&client_id={1}&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&client_id=XX&client_secret=XX&code=" + code + "&redirect_uri=http://127.0.0.1:18017/Home/AuthComplete";
        //var url = string.Format("?grant_type=authorization_code&client_id={0}&client_secret={1}&code={2}&redirect_uri={3}", mailchimp_clientid, mailchimp_secret, code, Url.Action("AuthComplete"));


        Response.Clear();

        StringBuilder sb = new StringBuilder();
        sb.Append("<html>");
        sb.AppendFormat(@"<body onload='document.forms[""form""].submit()'>");
        sb.AppendFormat("<form name='form' action='{0}' method='post'>", access_token_uri);

        sb.Append("<input type='hidden' name='grant_type' value='authorization_code'>");
        sb.AppendFormat("<input type='hidden' name='client_id' value='{0}'>", mailchimp_clientid2);
        sb.AppendFormat("<input type='hidden' name='client_secret' value='{0}'>", mailchimp_secret2);
        sb.AppendFormat("<input type='hidden' name='code' value='{0}'>", code);
        sb.AppendFormat("<input type='hidden' name='redirect_uri' value='{0}'>", "http://127.0.0.1:18017/Home/AuthComplete");
        // Other params go here

        sb.Append("</form>");
        sb.Append("</body>");
        sb.Append("</html>");

        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");
    }

}

It is step 4 that is killing me, not step 5.


回答1:


Step 4 is "Your application must make an out-of-band request to the access_token_uri using the code"

The main point here is "out of band". You have to build and send a post request server-side. The client should not have your mailchimp_secret

Your IncomingMailChimpToken could look like this :

    public ActionResult IncomingMailChimpToken(string code)
    {
        string mcPostData = String.Format(
            "grant_type={0}&client_id={1}&client_secret={2}&code={3}&redirect_url={4}",
            System.Web.HttpUtility.UrlEncode("authorization_code"),
            System.Web.HttpUtility.UrlEncode(mailchimp_clientid2),
            System.Web.HttpUtility.UrlEncode(mailchimp_secret2),
            System.Web.HttpUtility.UrlEncode(code),
            System.Web.HttpUtility.UrlEncode("http://127.0.0.1:18017/Home/AuthComplete")
            );
        WebRequest request = WebRequest.Create(access_token_uri);
        // Set the Method property of the request to POST.
        request.Method = "POST";
        request.ContentType = "application/json";
        byte[] byteArray = Encoding.UTF8.GetBytes(mcPostData);
        request.ContentLength = byteArray.Length;
        // Get the request stream.
        Stream dataStream = request.GetRequestStream();
        // Write the data to the request stream.
        dataStream.Write(byteArray, 0, byteArray.Length);
        // Close the Stream object.
        dataStream.Close();
        // Get the response.
        WebResponse response = request.GetResponse();
        // Get the stream containing content returned by the server.
        dataStream = response.GetResponseStream();
        // Open the stream using a StreamReader for easy access.
        StreamReader reader = new StreamReader(dataStream);
        // Read the content.
        string responseFromServer = reader.ReadToEnd();
        // Cleanup the streams and the response.
        reader.Close ();
        dataStream.Close ();
        response.Close ();

        // parse the json responseFromServer to extract token, expires_in and scope
        // and call AuthComplete with these params
    }



回答2:


You should send your request parameters in the body using post, if you were using curl php you would do this:

$value = http_build_query($params); //params is an array
curl_setopt($ch, CURLOPT_POSTFIELDS, $value);

Value should look like this:

grant_type=authorization_code&client_id=635959587059&client_secret=0da3e7744949e1406b7b250051ee1a95&code=1edf2589e664fd317f6a7ff5f97b42f7&redirect_uri=http%3A%2F%2F192.168.1.8%2Foauth%2Fcomplete.php

Notice that you should create a body request in the form a query string, don't send json, they wont't find your params. If you get an invalid grant response or something after doing this, check that the redirect uri you used to get the first code is EXACTLY the same as the one you are sending to get the token.

Also, to the ones using PHP, to match what the mailchimp documentation states use this:

curl_setopt($ch, CURLOPT_USERAGENT, 'oauth2-draft-v10');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));



回答3:


If you don't want to implement it yourself, there is this nice wrapper, which handles oAuth2 AND RESTapi-calls to MailChimp.

https://github.com/jamierytlewski/eepOAuth2-MVC



来源:https://stackoverflow.com/questions/12724581/mailchimp-oauth2-in-asp-net-keep-returning-invalid-grant

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!