We all started somewhere! Share your experience on the Get Advice: Let's Get Started Sweepstakes thread and be entered to win a $100 credit on your Constant Contact account.

Access token request Problem

JasonS845
Participant

Access token request Problem

We´re just starting with Constant Contact API and having problems with the athentication method in the mean time. We are trying to use OAuth2.0 as the documentation says in the following

link 

 

http://community.constantcontact.com/t5/Documentation/Authentication-using-OAuth-2-0-new-October-201...

However, when we request it we got the following error:

{  "error": "invalid_grant", "error_description": "Invalid verification code: xxxxxxxxxxxxxxxxx"}

 

It seems that we have to use  theclient_secret on any place but we have not idea. I hope this is clear..  Could someone

 

help us?

 

thanks

20 REPLIES 20
Ryan_D
Employee

Hey Jason,

 

If you dont mind posting your code or sending me a PM with it so I can troubleshoot it and see what is going on.  It sounds like your trying to get your Verified token and it is asking for the first token and it is lost during translation so it is giving back an invalid token. 

Ryan Davis
Quality Engineer
DanieleP
Regular Participant

Hi,

 

I have the same problem.

Could you please help me as well?

 

Thanks in advance

 

Dan

Hi Dan,

 

Sure, no problem.  The Client secret is associated with your API Key.  You can go to this link (and login if not already logged in) to view the client secret associated with your API Key.  

 

Here is a link to some example code for a simple OAuth 2 flow.  All you need to provide is a redirect URI where the user can click a link to generate the access token, your API Key, and client secret.

 

I hope that helps; let me know if you have any other questions.

 

Best Regards,

Shannon W.

API Support Specialist

DanieleP
Regular Participant

Hi Shannon,

 

Thanks a lot for your email.

The authentication is now working.

Only I got a message: "error_description": "Invalid verification code:....

The json file returned is ok...only my returned code is not considered valid in order to do the next steps...

Am I doing something wrong?

Thanks in advance

 

Dan

DanieleP
Regular Participant

I tried again but I cannot run any method as it says I have an invalid access token...

 

Please help!

 

Thanks

DanieleP
Regular Participant

This is the json result I am returned...

 

stdClass Object ( [error] => invalid_client [error_description] => Invalid client secret. )

 

but they are valid and the authentication works

DanieleP
Regular Participant

addtionally the cookies are not set....

Hi,

 

It would probably be best if I take a look at the code and try to make it work in my account.  Are you using the PHP or the .NET wrapper?  Could you email your code to webservices@constantcontact.com so we can take a look?

 

Thanks!

 

Best Regards,

Shannon W.

API Support Specialist

DanieleP
Regular Participant

Hi Shannon,

 

Thanks for your reply. I am using PHP.

I am sending you now an email.

 

Just a question.. the redirect_uri has to be HTTPS and not HTTP? And if so, Can I also use an external redirect, e.g. https://google.com or https://facebook.com just to get the token?

 

Thanks in advance

 

Dan

Hi,

 

Perfect, one of us will respond to your email at our soonest opportunity.

 

As for the redirect url, it does not have to be https.  It can be either https or http.  Mine is HTTP in fact.

 

Best Regards,

Shannon W.

API Support Specialist

Hello Dan,

 

The redirect_uri doesn't have to be SSL (HTTPS).  If you are using server flow, you can use whatever redirect URI you want, but you must have hosted there some script or application that can obtain the authorization code that will be sent there when browser is redirected to the redirect uri after you login and grant access (authorize), and then the script or application must be able to make a second request to our systems to exchange the authorization code for the access token. Capture the response and if your request was made properly, it will include the JSON containing the access token you need to store and use for additional API requests.

 

You can have a redirect uri that gets the authorization code, then provides it to an outside server, which can then make a cURL request to get the token, as well. After authorizing and granting access, our system will always redirect to your redirect uri, however, and this must match the one provided  in your API Key settings.

 

I hope that helps.

Mark Coleman
Support Engineer
DanieleP
Regular Participant

Hi Mark,

 

Thanks for your reply and emails.

I tried to reply many times to your emails but the message results undeliverable...

 

By the way, we succeeded with the authentication!

 

But when we try to display some user's data, e.g. contact list we are returned a HTTP error...

 

Any idea? thanks again

 

Constant Contact HTTP Request Exception:

HTTP Status 500 -


type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

com.roving.webservices.WebServiceException: the provided API key  is either disable or inavailalble
	com.roving.webservices.services.ApplicationKeyServiceImpl.validateAPIKey(ApplicationKeyServiceImpl.java:80)
	com.roving.webservices.auth.WSProtectedResourceProcessingFilter.validateOAuthParams(WSProtectedResourceProcessingFilter.java:38)
	org.springframework.security.oauth.provider.OAuthProviderProcessingFilter.doFilter(OAuthProviderProcessingFilter.java:124)
	org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
	org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91)
	org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
	org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
	org.springframework.security.ui.basicauth.BasicProcessingFilter.doFilterHttp(BasicProcessingFilter.java:174)
	org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
	org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
	org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
	org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
	org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
	com.roving.webservices.auth.BlockLoginFilter.doFilter(BlockLoginFilter.java:35)
	org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
	org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
	org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
	org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
	com.roving.webservices.filters.WSResteasyRequestFilter.doFilter(WSResteasyRequestFilter.java:88)
	com.roving.webservices.filters.HTTPSSLFilter.doFilter(HTTPSSLFilter.java:58)
	org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)

Hello,

 

Can you PM me the email address your email replies were going to? To sent a personal message - click on my forum name, and find the link to send me a message in my profile.

 

Based on the error message, it appears your reuqest may not be formed correctly by your application. In OAuth 2, if you have already authenticated and obtained an Access token and stored it on your side, you would only provide the access token either in the header or as a parameter on the request URL for your API call.

 

Make sure your script is set to format requests for OAuth 2, rather than basic or OAuth 1.0a.  If you're using the wrapper library, this is accomplished where you instantiated the ConstantContact object.

 

If you can post some of your code here with any unique identifyers (account credentials) removed, or simply send them as a text file attachment to webservices@constantcontact.com, we can take a look and try to offer more specific advice.

 

Mark Coleman
Support Engineer
DanieleP
Regular Participant

Hi Mark,

 

I send my messages to webservices@constantcontact.com but they returned back.

I send another one right now and it seems it worked out.

I am using auth 2.0 and the PHP Wrapper as you suggested.

I saw that the authentication is successful and also the ConstantContact object is created.

Problems raise when I do something like: $ConstantContact->getContactSends(...

 

Thanks for your support...

 

Dan

Hi Dan,

 

We do seem to be having a little bit of difficulty receiving your attachments through our webservices email address.  I'm glad authentication is now working for you.  We'd like to view the code that you are using in the constantcontact.php file when it errors out--could you post it here with any sensitive information omitted, or respond to the email that we sent you from webservices@constantcontact.com?

 

Thanks!

 

 

Best Regards,

Shannon W.

API Support Specialist

DanieleP
Regular Participant

Hi Shannon,

 

Thanks for your email...

 

the first file is (constantcontact.php):

 

<?php
    require_once 'cc/ConstantContact.php';
    require_once 'cc/config.php';
    
    session_start ();

    if ($DatastoreUser) {
        $ConstantContact = new ConstantContact ( "oauth2", $apikey, $username, $accessToken )
    } else {
        $theRequest = urlencode ( $verificationURL );
        $auth_url='https://oauth2.constantcontact.com/oauth2/oauth/siteowner/authorize?response_type=code&client_id='
        . $apikey . '&redirect_uri='
        . $theRequest;

        header('Location:' . $auth_url);    
    }

?>

 

than I have the redirect file (cc.php) which is:

 

<?php

require_once ('cc/ConstantContact.php');
require_once ('cc/config.php');

$sessionConsumer = array ('username' => $_GET ["username"], 'access_token' => $_GET ["code"] );
$Datastore = new CTCTDataStore ();
$Datastore->addUser ( $sessionConsumer );
$username=$sessionConsumer['username'];
$DatastoreUser = $Datastore->lookupUser($username);

    if($DatastoreUser){


                $ConstantContact = new ConstantContact('oauth2', $apikey, $DatastoreUser['username'], $consumersecret);

            $lists=$ConstantContact->getLists();
        
            echo "lists=".$lists;
            
    }
?>

 

the exception os triggered when retrieving $ConstantContact->getLists()

 

Thanks again

 

Dan

Hi Dan,

 

From your code, it looks like you haven't yet exchanged the authorization code ('code') for an access token.  This is the flow I use for authentication:

 

<?php
require_once ('ConstantContact.php');
require_once ('config.php');
session_start ();

// Istantiate a new oAuth2 object by passing in all the necesssary
// information to authenticate
$oAuth2 = new CTCTOauth2 ( $apikey, $consumersecret, $verificationURL, $_GET ["code"] );

// trade your code in for an access token by doing a POST
$token = $oAuth2->getAccessToken ();

// store information into the array to pass into the DataStore object
$sessionConsumer = array ('username' => $_GET ["username"], 'access_token' => $token );

$Datastore = new CTCTDataStore ();
$Datastore->addUser ( $sessionConsumer );
if(isset($_SESSION["backto"]))
{
	// if you set a return url and have stored it into backto
	$returnURL = $_SESSION["backto"];
}
// refresh the page to where you want to send them
header('Location:' . $returnURL);
?>

 

 

 

Best Regards,

Shannon W.

API Support Specialist

DanieleP
Regular Participant

Hi Shannon,

 

Also this did not work for me.

 

I used also the following (example/ContactReporting.php) from your repository, but again it says my key is invalid...

 

<h2>Contact Reporting Data Example</h2>
<?php
session_start();
include_once('../ConstantContact.php');
$username = 'USERNAME';
$apiKey = 'APIKEY';
$consumerSecret = 'CONSUMERSECRET';

$Datastore = new CTCTDataStore();
$DatastoreUser = $Datastore->lookupUser($username);

if($DatastoreUser){
    $emailAddress = (isset($_GET['email_address'])) ? $_GET['email_address'] : '';
    $ConstantContact = new ConstantContact('oauth', $apiKey, $DatastoreUser['username'], $consumerSecret);
    // Fail if the email does not exist
    ?>
        <html>
        <head><title>Contact Email History</title></head>
        <body>
        <!--- Basic form for contact event search submission --->
        <form method="get" action="">
            Email Address: <input type="text" value="<?php echo $emailAddress; ?>" name="email_address"><br />
            Sends <input type="radio" name="event_type" value="sends"><br />
            Clicks <input type="radio" name="event_type" value="clicks"><br />
            Opens <input type="radio" name="event_type" value="opens"><br />
            Forwards <input type="radio" name="event_type" value="forwards"><br />
            OptOuts <input type="radio" name="event_type" value="optouts"><br />
            Bounces <input type="radio" name="event_type" value="bounces"><br />
            <br /><input type="submit" value="submit" name="submit">
        </form>
        </body>
        </html>
    <?php
    if($_GET['email_address']){
        $contactSearch = $ConstantContact->searchContactsByEmail($_GET['email_address']);
        if(!$contactSearch){exit('Email not found');}

            // Find the appropriate event type for the verified contact
            $page = (isset($_GET['nextLink'])) ? $_GET['nextLink'] : null;
            switch ($_GET['event_type']) {
                case 'sends':
                    $event = $ConstantContact->getContactSends($contactSearch[0], $page);
                    break;
                case 'clicks':
                    $event = $ConstantContact->getContactClicks($contactSearch[0], $page);
                    break;
                case 'opens':
                    $event = $ConstantContact->getContactOpens($contactSearch[0], $page);
                    break;
                case 'forwards':
                    $event = $ConstantContact->getContactForwards($contactSearch[0], $page);
                    break;
                case 'optouts':
                    $event = $ConstantContact->getContactOptOuts($contactSearch[0], $page);
                    break;
                case 'bounces':
                    $event = $ConstantContact->getContactBounces($contactSearch[0], $page);
                    break;
            }

            // Display the results of the search
            if(count($event)>0){
                echo "<h3>There are ".count($event['events'])." ".$_GET['event_type']." for ".$_GET['email_address']."</h3>";
                if($event['nextLink']){
                    echo '<a href="contactReporting.php?nextLink='.$event['nextLink'].'&email_address='.$_GET['email_address'].'&event_type='.$_GET['event_type'].'"> Next Page</a>';
                }
                echo "<table>";
                foreach ($event['events'] as $e){
                    foreach ($e as $key=>$value){
                        echo "<tr><td style='font-weight: bold;'>".$key."</td><td>".$value."</td></tr>";
                    }
                    echo "<tr><td><br /></td><td></td></tr>";
                }
                echo "</table>";
            }
    }
} else {echo ' Click <a href="example_verification.php?apiKey='.$apiKey.'&secret='.$consumerSecret.'&return='.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'].'">here</a> to authorize';}

DanieleP
Regular Participant

It works now!

 

Sorry to trouble you!

 

I had some problems with the naming of variables in the last example.

Thanks for the update; I'm glad you got it working!

 

Best Regards,

Shannon W.

API Support Specialist

Developer Portal

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

Visit Page