The Community is hosting an End of Summer sweepstakes! Participants must complete tasks to earn tickets that will enter them with a chance to win a free year of Constant Contact and other great prizes!*
*No Purchase Necessary. For Official Rules, visit here. Constant Contact’s End of Summer 2020 Sweepstakes ends on October, 20, 2020 at 11:50 PM EST.

401 Error on attempt to create Activity (OAuth)

Highlighted
Occasional Contributor

401 Error on attempt to create Activity (OAuth)

I'm creating a PHP application that will need to occasionally perform bulk updates of contacts on Constant Contact. So, I've been attempting to use the Activities API. 

 

Unfortunately, this has not been working out well. My current code to post, put, or get individual contacts (using OAuth) is working perfectly well. Theoretically, the only modifications I would have to make to the code to perform the HTTP POST is to properly encode the data as per the Activities documentation (which I have verified that I am doing), change the Content-Type in the header (x-www-form-urlencoded rather than application/atom+xml;type=entry), and of course, to post to the correct URI (for activities, I'm posting to https://api.constantcontact.com/ws/customers/<username>/activities).

 

The error I'm getting is 'HTTP Status 401 - Invalid signature for signature method HMAC-SHA1'. Based on past experience, this sort of error always came down to an error in the OAuth signing. Here, though, that's doesn't seem to be the case. The same code is responsible for posting xml data, and is working fine in that context. Any guidance on what a 401 error could point to here?

 

Sample post data to create the activity (exactly what is set to CURLOPT_POSTFIELDS):

activityType=SV_ADD&data=Email+Address%2CFirst+Name%2CLast+Name%2CHome+Phone%2CWork+Phone%2CAddress+Line+1%2CCity%2CUS+State%2CCountry%2CZip%2CSub+Zip%0Aheather.byington%40fayebsg.com%2CJason%2CStatham%2C%28818%29+227-5130%2C%28818%29+227-5130%2CSampleAddress%2CSampleCity%2CCA%2CUSA%2C91367%2C%0Asample.email%40nowhere.com%2CStatham%2CJason%2C%2C%2C%2CValencia%2CCA%2CUnited+States%2C91355%2C%0A&lists=http%3A%2F%2Fapi.constantcontact.com%2Fws%2Fcustomers%2F<url-coded username>%2Flists%2F1

 

Sample header (precisely what is set to CURLOPT_HTTPHEADER):

Array( [0] => Authorization: OAuth oauth_version="1.0",oauth_nonce="c1b3b920e884ce775749f84645973143",oauth_timestamp="1303103990",oauth_consumer_key="<key>",oauth_token="<token>",oauth_signature_method="HMAC-SHA1",oauth_signature="<sig>" [1] => Content-Type:application/x-www-form-urlencoded [2] => Content-Length: 516 )

 

 

Edit: Actually, here's some sample code as well.

 

This function performs the OAuth work:

 

 

function perform_signed_post($url, $postData, $contentType = 'application/atom+xml;type=entry') {
        $token = new OAuthToken($this->access_token, $this->access_token_secret);
        $token_request = OAuthRequest::from_consumer_and_token($this->oauth_consumer, $token, 'POST', $url);
        $token_request->sign_request($this->sig_method, $this->oauth_consumer, $token);
        $token_request_header = $token_request->to_header();
        $response = self::perform_curl_post($token_request_header, $url, $postData, $contentType);
        return $response;
    }

 

 

 

 

This function does the actual HTTP POST:

 

public static function perform_curl_post($auth_header, $url, $postData, $contentType)
    {
        $session = curl_init($url);
        curl_setopt($session, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($session, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($session, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($session, CURLOPT_POST, 1);
        curl_setopt($session, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($session, CURLOPT_HTTPHEADER, array($auth_header,'Content-Type: '.$contentType, 'Content-Length: '.strlen($postData)));
        $response = curl_exec($session);
        $ret = '';
        if(!$response) {
            $ret = array('error' => curl_error($session), 'status' => curl_getinfo($session, CURLINFO_HTTP_CODE), 'data' => null);
        }
        else {
            $ret = array('error' => null, 'status' => curl_getinfo($session, CURLINFO_HTTP_CODE), 'data'=>$response);
        }
        curl_close($session);
        return $ret;
    }

 

 

7 REPLIES 7
Highlighted
Employee

Re: 401 Error on attempt to create Activity (OAuth)

It appears that this might actually be an issue on our end as I am running into the same issue posting this activity, however when using basic authentication it does seem to work properly. I am going to discuss this with our engineering team and will get back to you as soon as I have anymore information on this. I apologize for any inconvenience that this has caused.

David J

Highlighted
Occasional Contributor

Re: 401 Error on attempt to create Activity (OAuth)

Only a minor inconvenience so far, there's always other work to do. :) I appreciate the quick response. If I may ask another question in this same thread (I'll make another one if necessary):

 

This application needs to use oob authentication. Unfortunately, when a user enters their credentials and presses the Confirm Access button, they are redirected to a 403 Forbidden page. The verifier is present in the query string, and using it does allow access, but it's a pretty scary thing for users to encounter. This only recently (last couple weeks) started happening, with no modifications to our application.

Highlighted
Occasional Contributor

Re: 401 Error on attempt to create Activity (OAuth)

Any update on this?

Highlighted
Moderator

Re: 401 Error on attempt to create Activity (OAuth)

Our engineering team is looking at this defect and we plan to have it fixed in an upcoming release.  At this time, we are not able to provide any dates as to when this will be.  I will follow up on this with our team to try to get a better time estimate on this.

 

As an aside, the oob option for OAuth is indeed a valid flow for users to go through.  For usability purposes though, this is the least recommended flow.  Using a callback URL to process the verify token automatically without any user interaction is always prefered as it makes the flow easier for them to understand and follow.  Is there a technical limitation that is preventing this flow for your application?  I'd be interested in hearing more about the design flows that prompted you to choose the oob option instead of a callback URL.

Dave Berard
Senior Product Manager, Constant Contact
Highlighted
Occasional Contributor

Re: 401 Error on attempt to create Activity (OAuth)

Yeah, there's a technical reason. The application we're integrating Constant Contact with is sometimes operated in a hosted environment, so in many circumstances, we wouldn't need to use the oob flow. However, it is also commonly operated on an internal intranet, and is not visible from outside that network, so we need to make the oob flow an option.

Highlighted
Moderator

Re: 401 Error on attempt to create Activity (OAuth)

There is one additional option that you can use, this is the same flow that a program like Tweetdeck or other installed Twitter/Facebook clients use.

 

The change you make is to have the intranet applications that are not visable to the word have an end point that is visible, such as your company website.  You can connect to this through your intranet and then make the callback URL point to that website endpoint.  Once the website receives the verifier, you can then pass it back through your intranet to the application. 

 

This additional step would be fairly easy to handle by using the optional parameter feature of OAuth.  You can set up something like clientid=XXXXXX, pass that as one of the parameters of request and per the OAuth standard, we have to pass that back as part of the callback URL.  This way, you can identify the correct client application that needs to receive this information and pass it back to them. 

 

I hope to have an update on this defect today, will update once I do.

Dave Berard
Senior Product Manager, Constant Contact
Highlighted
Occasional Visitor

Re: 401 Error on attempt to create Activity (OAuth)

We're seeing the same behaviour: an activity POST action to populate a list is failing with OAuth, but works with the username/password mode of authentication. It must be related to decoding the form data, since if I replace the data parameter in the form with "data=something" I get a 500 error (not 401). Also, the clear list activity posts just fine with OAuth.

 

This is a pretty major blocker for us. Any timeline on a fix, or workaround to populate a list in bulk with OAuth?

 

Thanks,

Chuck

Tags (1)
Developer Portal

View API documentation, code samples, get your API key.

Visit Page

Constant Contact 2020 End of Summer Community Sweepstakes!

The Constant Contact User Community is hosting a sweepstakes. The more you participate, the more chances you have to win! Read on to learn more...

Read More
Featured