Access token expired in V3

AprilD761
Occasional Participant

Access token expired in V3

I am looking to upgrade constant contact api to V3 api. For making api calls I need the access token. I generated access token using OAuth2.0 Client Flow. And tested  api call get contacts. Its is working. After few times I call the api but gives the error unauthorized access token. It was because of the access token get expired. In OAuth2.0 Client Flow it is saying that the life span of access token in some hours.

 

So how I use this for long term use. That is I have to generate new access token time to time and it is not practical.

Currently I am using the api to retrieve/add/update contacts to constant contact account. In constant contact  api I don't face this type of issue, because there access token is not expired.

7 REPLIES 7
Jimmy_D
Moderator

Hello @AprilD761 ,

 

Thank you for reaching out to Constant Contact's API Support.

 

If you continue going through the oAuth documentation for v3 you will notice that it mentions a Refresh Token section after the Access Token section. You use the Refresh Token to get a new Access Token. You can find this documentation here


Regards,
Jimmy D.
Tier II API Support Engineer
AprilD761
Occasional Participant

Yes, I tried the OAuth2.0 Server Flow also.

As you mentioned, we use the Refresh Token to get a new Access Token. This will also expire. In step 4, we can generate Access Token and a Refresh Token using Authorization Code. And when the Access Token expired using the Refresh Token we can regenerate new Access Token and refresh token.

 

That is time to time Access Token get expired and using the refresh token we generate new access token.

 

So time to time I have to change the code. Right?

Hello,

 

Refresh Tokens do not expire the way that Access Tokens do.

 

When using the Server flow, you are given a Refresh Token as well as an Access Token. When your Access Token has expired, you can exchange the Refresh Token for a new Access Token as well as a new Refresh Token. You would then continue doing this with the new Refresh Tokens obtained.


Regards,
David B.
Tier II API Support Engineer

 

 

AprilD761
Occasional Participant

Hi, 

As you said

Refresh Tokens do not expire the way that Access Tokens do.

 

I got:  string(92) "{"error_description":"unknown, invalid, or expired refresh token","error":"invalid_grant"} "

 

My code is: 

function refreshToken($refreshToken, $clientId, $clientSecret) {
    $ch = curl_init();
    $base = 'https://idfed.constantcontact.com/as/token.oauth2';
    $url = $base . '?refresh_token=' . $refreshToken . '&grant_type=refresh_token';
    curl_setopt($ch, CURLOPT_URL, $url);
    $auth = $clientId . ':' . $clientSecret;
    $credentials = base64_encode($auth);
    $authorization = 'Authorization: Basic ' . $credentials;
    curl_setopt($ch, CURLOPT_HTTPHEADER, array($authorization));

    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}
$refreshToken = "xxxxxx";
$clientId="xxxxxxxx";
$clientSecret="xxxxxxxx";

var_dump(refreshToken($refreshToken,  $clientId, $clientSecret));

Hi @AprilD761,

 

Your code looks correct. You would get an error if somehow the $refreshToken was accidentally pulling in the Access Token instead of the previous Refresh Token. Since we cannot see the rest of the code I would ensure it is pulling in the correct value.


Regards,
Jimmy D.
Tier II API Support Engineer
LauraV545
Consulting & Training

If the access token is expired, will it return 401 The Access Token used is invalid, and after detecting that has happened, that is when to use the Refresh token to ask for another Access Token? Or is it recommended to periodically request a new access token to keep the Access Token from expiring?

FadyY8
Frequent Participant

I am not entirely sure what does CTCT thinks.

If any other developers out there need the code here it is for MVC C#


[Route("check_session_api")]
        public object CheckSessionAPI()
        {
            if (Session["ResponseAPI"] == null)
            {
                return "No result";
            }
            else
            {
                return Session["ResponseAPI"].ToString();
            }
        }


        [Route("api_request")]
        public ActionResult ApiRequest()
        {
            var url = "https://api.cc.email/v3/idfed" + "?client_id=" + apiKey + 
                "&redirect_uri=" + redirectURL + 
                "&scope=contact_data+campaign_data" + "&response_type=code";
            return RedirectPermanent(url);
        }

        [Route("api_response")]
        public object ApiResponse()
        {
            try
            {
                string code = Request.QueryString["code"];
                if (code != null)
                {
                    using (var webClient = new WebClient())
                    {
                        byte[] bytes = Encoding.UTF8.GetBytes(apiKey + ":" + client_secret);
                        var base64 = Convert.ToBase64String(bytes);

                        var client = new RestClient(tokenURL);
                        var request = new RestRequest(Method.POST);
                        request.AddHeader("Authorization", "Basic " + base64);
                        request.AddParameter("code", code);
                        request.AddParameter("redirect_uri", redirectURL);
                        request.AddParameter("grant_type", "authorization_code");

                        IRestResponse res = client.Execute(request);

                        if (res.StatusCode.ToString().ToLower().IndexOf("bad") < 0)
                        {
                            Session["ResponseAPI"] = res.Content;
                        }
                    }
                    return RedirectToAction("Index", "Home");
                }
                return null;
            }
            catch (Exception ex)
            {
                return ex;
            }
        }


        [Route("api_refresh")]
        public object ApiRefresh(string refresh_token)
        {
            try
            {
                using (var webClient = new WebClient())
                {
                    var client = new RestClient(tokenURL);
                    var request = new RestRequest(Method.POST);
                    request.AddHeader("Authorization", "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(apiKey + ":" + client_secret)));
                    request.AddParameter("refresh_token", refresh_token);
                    request.AddParameter("grant_type", "refresh_token");
                    IRestResponse res = client.Execute(request);

                    if (res.StatusCode.ToString().ToLower().IndexOf("bad") < 0)
                    {
                        ///success
                        Session["ResponseAPI"] = res.Content;                        
                    } else
                    {
                        //failure                         
                        refresh_token = "{hard code the refresh token}";
                        return ApiRefresh(refresh_token);
                    }
                    return Session["ResponseAPI"];                    
                }
            }
            catch (Exception ex)
            {
                return ex;
            }
        }

 Now the major PROBLEM with this design are:

1) You must hard code the refresh token and good luck with that !!!!

2) You must be logged in into https://developer.constantcontact.com for this whole thing to even work!! That's right. So if you are a developer like me and write this code for a website to collect subscriber emails you are screwed (no other way to put that).

 

Constant Contact Team, You need to fix this and asap otherwise I will be happy to take it away from you to mailchimp.

UGH!!!

Developer Portal

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

Visit Page