com.ibm.sbt.security.authentication.oauth.consumer.OAuth2Handler.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.sbt.security.authentication.oauth.consumer.OAuth2Handler.java

Source

/****************************************************************************************
 * Copyright 2012 IBM Corp.                                                                   *
 *                                                                                      *
 * Licensed under the Apache License, Version 2.0 (the "License");                      *
 * you may not use this file except in compliance with the License.                     *
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0   *
 *                                                                                      *
 * Unless required by applicable law or agreed to in writing, software                  *
 * distributed under the License is distributed on an "AS IS" BASIS,                    *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.             *
 * See the License for the specific language governing permissions and                  *
 * limitations under the License.                                                       *
 ****************************************************************************************/

package com.ibm.sbt.security.authentication.oauth.consumer;

//import java.awt.Desktop;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import com.ibm.commons.Platform;
import com.ibm.commons.runtime.Context;
import com.ibm.commons.runtime.util.UrlUtil;
import com.ibm.commons.util.PathUtil;
import com.ibm.commons.util.StringUtil;
import com.ibm.commons.util.io.StreamUtil;
import com.ibm.commons.util.profiler.Profiler;
import com.ibm.commons.util.profiler.ProfilerAggregator;
import com.ibm.commons.util.profiler.ProfilerType;
import com.ibm.sbt.core.configuration.Configuration;
import com.ibm.sbt.security.authentication.oauth.OAuthException;
import com.ibm.sbt.security.credential.store.CredentialStore;
import com.ibm.sbt.security.credential.store.CredentialStoreException;
import com.ibm.sbt.security.credential.store.CredentialStoreFactory;
import com.ibm.sbt.security.authentication.oauth.consumer.servlet.OA2Callback;
import com.ibm.sbt.service.util.ServiceUtil;
import com.ibm.sbt.services.util.AnonymousCredentialStore;
import com.ibm.sbt.services.util.SSLUtil;

/**
 * @author Manish Kataria
 */

public class OAuth2Handler extends OAuthHandler {

    public static final int EXPIRE_THRESHOLD = 60; // 60sec = 1min

    private String appId;
    private String client_uri;
    private String authorization_code;
    private String accessToken;
    private String refreshToken;
    private Date issuedOn;
    private String expiresIn;
    private String tokenType;
    private String servicename;
    private String authorizationURL;
    private String accessTokenURL;
    private String serviceName;
    private String consumerKey;
    private String consumerSecret;
    private String applicationPage;
    private int expireThreshold;
    private boolean forceTrustSSLCertificate;
    private AccessToken accessTokenObject;

    // Type used to store the credentials
    public static final String ACCESS_TOKEN_STORE_TYPE = "OAUTH2_ACCESS_TOKEN_STORE";
    public static final String CONSUMER_TOKEN_STORE_TYPE = "OAUTH2_CONSUMER_TOKEN_STORE";

    // Persistence store code
    private boolean storeRead;
    private String credentialStore;
    private static final ProfilerType profilerLoadCredentialStore = new ProfilerType(
            "OAuth: Load a token from the store"); //$NON-NLS-1$
    private static final ProfilerType profilerAcquireToken = new ProfilerType(
            "OAuth: Acquire a token from the service"); //$NON-NLS-1$
    private static final ProfilerType profilerRenewToken = new ProfilerType(
            "OAuth: Renew a token from the provider"); //$NON-NLS-1$
    private static final ProfilerType profilerDeleteToken = new ProfilerType(
            "OAuth: Delete a token from the store"); //$NON-NLS-1$

    //for logging 
    private static final String sourceClass = OAuth1Handler.class.getName();
    private static final Logger logger = Logger.getLogger(sourceClass);

    public OAuth2Handler() {
        this.setExpireThreshold(EXPIRE_THRESHOLD);
    }

    @Override
    public boolean isInitialized() {
        return accessToken != null;
    }

    /**
     * Generates the authorization url for fetching the authorization tokens
     * 
     * https://apps.lotuslive.com/manage/oauth2/authorize?
     *                    response_type=code&
     *                    client_id=<client_id>&
     *                    callback_uri=<callback_uri>
     * 
     * @return URL
     */
    public String getAuthorizationNetworkUrl() {
        StringBuilder url = new StringBuilder();
        try {
            url.append(getAuthorizationURL());
            url.append('?');
            url.append(Configuration.OAUTH2_RESPONSE_TYPE);
            url.append('=');
            url.append(Configuration.OAUTH2_CODE);
            url.append('&');
            url.append(Configuration.OAUTH2_CLIENT_ID);
            url.append('=');
            url.append(URLEncoder.encode(consumerKey, "UTF-8"));
            url.append('&');
            url.append(Configuration.OAUTH2_CALLBACK_URI);
            url.append('=');
            url.append(URLEncoder.encode(client_uri, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
        }
        return url.toString();
    }

    /**
     ** Authorization: OAuth 
     *                callback_uri="<callback_uri>", 
     *                client_secret="<client_secret>",
     *                client_id="<client_id>", 
     *                grant_type="authorization_code", 
     *                code="<authorization_code>"
     * 
     * Calls the server URL with Authorization header and gets back following values:
     *    access_token, refresh_token, issued_on expires_in, token_type.
     * 
     * @throws Exception
     */
    public void getAccessTokenForAuthorizedUser() throws Exception {
        if (logger.isLoggable(Level.FINEST)) {
            logger.entering(sourceClass, "getAccessTokenForAuthorizedUser", new Object[] {});
        }
        HttpGet method = null;
        int responseCode = HttpStatus.SC_OK;
        String responseBody = null;
        InputStream content = null;
        try {
            HttpClient client = new DefaultHttpClient();
            if (forceTrustSSLCertificate)
                client = (DefaultHttpClient) SSLUtil.wrapHttpClient((DefaultHttpClient) client);
            StringBuffer url = new StringBuffer(2048);
            url.append(getAccessTokenURL()).append("?");
            url.append(Configuration.OAUTH2_CALLBACK_URI).append('=')
                    .append(URLEncoder.encode(client_uri, "UTF-8"));
            url.append('&');
            url.append(Configuration.OAUTH2_CLIENT_ID).append('=').append(URLEncoder.encode(consumerKey, "UTF-8"));
            url.append('&');
            url.append(Configuration.OAUTH2_CLIENT_SECRET).append('=')
                    .append(URLEncoder.encode(consumerSecret, "UTF-8"));
            url.append('&');
            url.append(Configuration.OAUTH2_GRANT_TYPE).append('=').append(Configuration.OAUTH2_AUTHORIZATION_CODE);
            url.append('&');
            url.append(Configuration.OAUTH2_CODE).append('=')
                    .append(URLEncoder.encode(authorization_code, "UTF-8"));
            method = new HttpGet(url.toString());
            HttpResponse httpResponse = client.execute(method);
            responseCode = httpResponse.getStatusLine().getStatusCode();
            if (logger.isLoggable(Level.FINEST)) {
                logger.log(Level.FINEST, "OAuth2.0 network call to fetch token :" + url, responseCode);
            }
            content = httpResponse.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(content));
            try {
                responseBody = StreamUtil.readString(reader);
            } finally {
                StreamUtil.close(reader);
            }
        } catch (Exception e) {
            throw new OAuthException(e, "getAccessToken failed with Exception: <br>" + e);
        } finally {
            if (content != null) {
                content.close();
            }
        }
        if (responseCode != HttpStatus.SC_OK) {
            getAccessTokenForAuthorizedUsingPOST();
            return;
            //         if (responseCode == HttpStatus.SC_UNAUTHORIZED) {
            //            throw new Exception("getAccessToken failed with Response Code: Unauthorized (401),<br>Msg: " + responseBody);
            //         } else if (responseCode == HttpStatus.SC_BAD_REQUEST) {
            //            throw new Exception("getAccessToken failed with Response Code: Bad Request (400),<br>Msg: " + responseBody);
            //         } else if (responseCode == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
            //            throw new Exception("getAccessToken failed with Response Code: Internal Server error (500),<br>Msg: " + responseBody);
            //         } else {
            //            throw new Exception("getAccessToken failed with Response Code: (" + responseCode + "),<br>Msg: " + responseBody);
            //         }
        } else {
            setOAuthData(responseBody); //save the returned data
        }

    }

    /*
     * 
    grant_type
     REQUIRED.  Value MUST be set to "authorization_code".
    code
     REQUIRED.  The authorization code received from the
     authorization server.
    redirect_uri
     REQUIRED, if the "redirect_uri" parameter was included in the
     authorization request as described in Section 4.1.1, and their
     values MUST be identical.
    client_id
     REQUIRED, if the client is not authenticating with the
     authorization server as described in Section 3.2.1.
        
     */

    public void getAccessTokenForAuthorizedUsingPOST() throws Exception {

        if (logger.isLoggable(Level.FINEST)) {
            logger.entering(sourceClass, "getAccessTokenForAuthorizedUsingPOST", new Object[] {});
        }

        HttpPost method = null;
        int responseCode = HttpStatus.SC_OK;
        String responseBody = null;
        InputStream content = null;
        try {
            HttpClient client = new DefaultHttpClient();
            if (forceTrustSSLCertificate)
                client = (DefaultHttpClient) SSLUtil.wrapHttpClient((DefaultHttpClient) client);
            StringBuffer url = new StringBuffer(2048);

            // This works for Smartcloud
            /*         url.append(getAccessTokenURL()).append("?");
                     url.append(Configuration.OAUTH2_CALLBACK_URI).append('=').append(URLEncoder.encode(client_uri, "UTF-8"));
                     url.append('&');
                     url.append(Configuration.OAUTH2_CLIENT_ID).append('=').append(URLEncoder.encode(consumerKey, "UTF-8"));
                     url.append('&');
                     url.append(Configuration.OAUTH2_CLIENT_SECRET).append('=').append(URLEncoder.encode(consumerSecret, "UTF-8"));
                     url.append('&');
                     url.append(Configuration.OAUTH2_GRANT_TYPE).append('=').append(Configuration.OAUTH2_AUTHORIZATION_CODE);
                     url.append('&');
                     url.append(Configuration.OAUTH2_CODE).append('=').append(URLEncoder.encode(authorization_code, "UTF-8"));
                     System.err.println("url used here "+url);
                     method = new HttpPost(url.toString());*/

            // This works for connections
            // add parameters to the post method  
            method = new HttpPost(getAccessTokenURL());
            List<NameValuePair> parameters = new ArrayList<NameValuePair>();
            parameters.add(new BasicNameValuePair(Configuration.OAUTH2_CALLBACK_URI,
                    URLEncoder.encode(client_uri, "UTF-8")));
            parameters.add(new BasicNameValuePair(Configuration.OAUTH2_CLIENT_ID,
                    URLEncoder.encode(consumerKey, "UTF-8")));
            parameters.add(new BasicNameValuePair(Configuration.OAUTH2_CLIENT_SECRET,
                    URLEncoder.encode(consumerSecret, "UTF-8")));
            parameters.add(new BasicNameValuePair(Configuration.OAUTH2_GRANT_TYPE,
                    Configuration.OAUTH2_AUTHORIZATION_CODE));
            parameters.add(new BasicNameValuePair(Configuration.OAUTH2_CODE,
                    URLEncoder.encode(authorization_code, "UTF-8")));
            UrlEncodedFormEntity sendentity = new UrlEncodedFormEntity(parameters, HTTP.UTF_8);
            method.setEntity(sendentity);
            HttpResponse httpResponse = client.execute(method);
            responseCode = httpResponse.getStatusLine().getStatusCode();

            if (logger.isLoggable(Level.FINEST)) {
                logger.log(Level.FINEST, "OAuth2.0 network call to fetch token :" + getAccessTokenURL(),
                        responseCode);
            }

            content = httpResponse.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(content));
            try {
                responseBody = StreamUtil.readString(reader);
            } finally {
                StreamUtil.close(reader);
            }
        } catch (Exception e) {
            throw new OAuthException(e, "getAccessToken failed with Exception: <br>");
        } finally {
            if (content != null) {
                content.close();
            }
        }
        if (responseCode != HttpStatus.SC_OK) {
            String exceptionDetail = buildErrorMessage(responseCode, responseBody);
            if (exceptionDetail != null) {
                String msg = "Unable to retrieve access token because \"{0}\". Please check the access token URL is valid, current value: {1}.";
                msg = MessageFormat.format(msg, exceptionDetail, getAccessTokenURL());
                throw new OAuthException(null, msg);
            }
        } else {
            setOAuthData(responseBody); //save the returned data
        }
    }

    @Override
    public String createAuthorizationHeader() {
        if (logger.isLoggable(Level.FINEST)) {
            logger.entering(sourceClass, "createAuthorizationHeader", new Object[] {});
        }

        if (logger.isLoggable(Level.FINEST)) {
            logger.log(Level.FINEST, "Security Header :" + "Bearer " + accessToken);
        }
        return "Bearer " + accessToken;
    }

    protected void setOAuthData(String responseBody) {
        accessToken = getTokenValue(responseBody, Configuration.OAUTH2_ACCESS_TOKEN);
        refreshToken = getTokenValue(responseBody, Configuration.OAUTH2_REFRESH_TOKEN);
        String issuedOnDate = getTokenValue(responseBody, Configuration.OAUTH2_ISSUEDON);
        try {
            issuedOn = new Date(Long.valueOf(issuedOnDate));
        } catch (Exception e) {
        }
        expiresIn = getTokenValue(responseBody, Configuration.OAUTH2_EXPIRESIN);
        tokenType = getTokenValue(responseBody, Configuration.OAUTH2_TOKENTYPE);
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getClient_uri() {
        return client_uri;
    }

    public void setClient_uri(String client_uri) {
        this.client_uri = client_uri;
    }

    public String getAuthorization_code() {
        return authorization_code;
    }

    public void setAuthorization_code(String authorization_code) {
        this.authorization_code = authorization_code;
    }

    @Override
    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public AccessToken getAccessTokenObject() {
        return accessTokenObject;
    }

    public void setAccessTokenObject(AccessToken accessTokenObject) {
        this.accessTokenObject = accessTokenObject;
    }

    public String getRefreshToken() {
        return refreshToken;
    }

    public void setRefreshToken(String refreshToken) {
        this.refreshToken = refreshToken;
    }

    public Date getIssuedOn() {
        return issuedOn;
    }

    public void setIssuedOn(Date issuedOn) {
        this.issuedOn = issuedOn;
    }

    public String getExpiresIn() {
        return expiresIn;
    }

    public void setExpiresIn(String expireIn) {
        this.expiresIn = expireIn;
    }

    public String getTokenType() {
        return tokenType;
    }

    public void setTokenType(String tokenType) {
        this.tokenType = tokenType;
    }

    @Override
    public String getAuthType() {
        return Configuration.AUTH_TYPE_OAUTH2;
    }

    public String getServicename() {
        return servicename;
    }

    public void setServicename(String servicename) {
        this.servicename = servicename;
    }

    public void setAuthorizationURL(String authorizationURL) {
        this.authorizationURL = authorizationURL;
    }

    @Override
    public String getAuthorizationURL() {
        return authorizationURL;
    }

    public String getAccessTokenURL() {
        return accessTokenURL;
    }

    public void setAccessTokenURL(String accessTokenURL) {
        this.accessTokenURL = accessTokenURL;
    }

    private void readConsumerToken() throws OAuthException {
        if (!storeRead) {
            try {
                CredentialStore factory = CredentialStoreFactory.getCredentialStore(getCredentialStore());
                if (factory != null) {
                    ConsumerToken consumerToken = (ConsumerToken) factory.load(getServiceName(),
                            CONSUMER_TOKEN_STORE_TYPE, null);
                    if (consumerToken != null) {
                        storeRead = true;
                        if (StringUtil.isNotEmpty(consumerToken.getConsumerKey())) {
                            setConsumerKey(consumerToken.getConsumerKey());
                        }
                        if (StringUtil.isNotEmpty(consumerToken.getConsumerSecret())) {
                            setConsumerSecret(consumerToken.getConsumerSecret());
                        }
                        if (StringUtil.isNotEmpty(consumerToken.getAuthorizationUri())) {
                            setAuthorizationURL(consumerToken.getAuthorizationUri());
                        }
                        if (StringUtil.isNotEmpty(consumerToken.getAccessTokenUri())) {
                            setAccessTokenURL(consumerToken.getAccessTokenUri());
                        }
                    }
                }
            } catch (CredentialStoreException cse) {
                throw new OAuthException(cse, cse.getMessage());
            }
        }
    }

    public void setCredentialStore(String credentialStore) {
        this.credentialStore = credentialStore;
    }

    public String getCredentialStore() {
        return credentialStore;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    public String getServiceName() {
        return serviceName;
    }

    public void setConsumerSecret(String consumerSecret) {
        this.consumerSecret = consumerSecret;
    }

    public String getConsumerSecret() {
        return consumerSecret;
    }

    public void setConsumerKey(String consumerKey) {
        this.consumerKey = consumerKey;
    }

    public String getConsumerKey() {
        return consumerKey;
    }

    //Persistance related code

    public AccessToken acquireToken() throws OAuthException {
        return acquireToken(false);
    }

    public AccessToken acquireToken(boolean login) throws OAuthException {
        return acquireToken(login, false);
    }

    public AccessToken acquireToken(boolean login, boolean force) throws OAuthException {
        if (Profiler.isEnabled()) {
            ProfilerAggregator agg = Profiler.startProfileBlock(profilerAcquireToken, "");
            long ts = Profiler.getCurrentTime();
            try {
                return _acquireToken(login, force);
            } finally {
                Profiler.endProfileBlock(agg, ts);
            }
        } else {
            return _acquireToken(login, force);
        }
    }

    /*
     * This method searches for existing token in store.
     * It can also conditionally trigger the OAuth2 Dance to procure new tokens
     * When parameter force is True, we reperform the Oauth Dance.
     * When login is True, we reperform the Oauth dance only when tokens are not available in store or bean
     */

    public AccessToken _acquireToken(boolean login, boolean force) throws OAuthException {
        Context context = Context.get();
        AccessToken tk;

        // If force is used, then login must be requested
        if (force) {
            login = true;
        }

        String userId = getUserId();

        // Look for a token in the store
        // If the user is anonymous, then the token might had been stored in the session
        if (!force) {

            if (getAccessTokenObject() != null) {
                // read from the local bean if accesstoken is present
                tk = getAccessTokenObject();
            } else {
                tk = context.isCurrentUserAnonymous()
                        ? (AccessToken) AnonymousCredentialStore.loadCredentials(context, getAppId(),
                                getServiceName())
                        : findTokenFromStore(context, userId);
            }

            // check if token needs to be renewed
            if (tk != null) {
                if (shouldRenewToken(tk)) { //based on expiration date, check if token needs to be renewed.
                    return renewToken(tk);
                }
                return tk;
            }
        }
        if (login) {
            deleteToken();
            setAccessTokenObject(null);
            performOAuth2Dance();
        }
        return null;
    }

    protected AccessToken findTokenFromStore(Context context, String userId) throws OAuthException {
        if (Profiler.isEnabled()) {
            ProfilerAggregator agg = Profiler.startProfileBlock(profilerLoadCredentialStore, "");
            long ts = Profiler.getCurrentTime();
            try {
                return _findTokenFromStore(context, userId);
            } finally {
                Profiler.endProfileBlock(agg, ts);
            }
        } else {
            return _findTokenFromStore(context, userId);
        }
    }

    protected AccessToken _findTokenFromStore(Context context, String userId) throws OAuthException {
        readConsumerToken();

        if (StringUtil.isEmpty(userId)) {
            userId = getUserId();
            // Anonymous is not valid
            if (StringUtil.isEmpty(userId)) {
                return null;
            }
        }
        try {
            CredentialStore credStore = CredentialStoreFactory.getCredentialStore(getCredentialStore());
            if (credStore != null) {
                // Find the token for this user
                AccessToken token = (AccessToken) credStore.load(getServiceName(), ACCESS_TOKEN_STORE_TYPE, userId);
                if (token != null) {
                    return token;
                }
            }
        } catch (CredentialStoreException cse) {
            throw new OAuthException(cse, "Error finding credentials from the store");
        }
        return null;
    }

    // ==========================================================
    //  Delete token
    // ==========================================================

    public void deleteToken() throws OAuthException {
        if (Profiler.isEnabled()) {
            ProfilerAggregator agg = Profiler.startProfileBlock(profilerDeleteToken, "");
            long ts = Profiler.getCurrentTime();
            try {
                _deleteToken(Context.get(), null);
            } finally {
                Profiler.endProfileBlock(agg, ts);
            }
        } else {
            _deleteToken(Context.get(), null);
        }
    }

    protected void _deleteToken(Context context, String userId) throws OAuthException {
        readConsumerToken();

        if (StringUtil.isEmpty(userId)) {
            userId = getUserId();
            if (StringUtil.isEmpty(userId)) {
                return;
            }

        }
        if (StringUtil.equals(userId, "anonymous")) {
            AnonymousCredentialStore.deleteCredentials(context, getAppId(), getServiceName());
        } else {
            try {
                CredentialStore credStore = CredentialStoreFactory.getCredentialStore(getCredentialStore());
                if (credStore != null) {
                    // Find the token for this user
                    credStore.remove(getServiceName(), ACCESS_TOKEN_STORE_TYPE, getUserId());
                }
            } catch (CredentialStoreException cse) {
                throw new OAuthException(cse, "Error trying to delete Token.");
            }
        }
    }

    //  Renew the token
    // ==========================================================

    public AccessToken renewToken() throws OAuthException {
        return renewToken(null);
    }

    public AccessToken renewToken(AccessToken token) throws OAuthException {
        if (Profiler.isEnabled()) {
            ProfilerAggregator agg = Profiler.startProfileBlock(profilerRenewToken, "");
            long ts = Profiler.getCurrentTime();
            try {
                return _renewToken(token);
            } finally {
                Profiler.endProfileBlock(agg, ts);
            }
        } else {
            return _renewToken(token);
        }
    }

    /*
     * This method uses the existing refresh token and renews the access token from access token url
     */
    protected AccessToken _renewToken(AccessToken token) throws OAuthException {
        HttpGet method = null;
        AccessToken renewedtoken = null;
        int responseCode = HttpStatus.SC_OK;
        String responseBody = null;
        InputStream content = null;
        try {
            HttpClient client = new DefaultHttpClient();
            if (forceTrustSSLCertificate)
                client = (DefaultHttpClient) SSLUtil.wrapHttpClient((DefaultHttpClient) client);
            StringBuilder url = new StringBuilder();
            url.append(getAccessTokenURL()).append('?');
            url.append(Configuration.OAUTH2_CLIENT_ID);
            url.append('=');
            url.append(URLEncoder.encode(token.getConsumerKey(), "UTF-8"));
            url.append('&');
            url.append(Configuration.OAUTH2_CLIENT_SECRET);
            url.append('=');
            url.append(URLEncoder.encode(token.getTokenSecret(), "UTF-8"));
            url.append('&');
            url.append(Configuration.OAUTH2_GRANT_TYPE);
            url.append('=');
            url.append(Configuration.OAUTH2_REFRESH_TOKEN);
            url.append('&');
            url.append(Configuration.OAUTH2_REFRESH_TOKEN);
            url.append('=');
            url.append(URLEncoder.encode(token.getRefreshToken(), "UTF-8"));
            method = new HttpGet(url.toString());
            HttpResponse httpResponse = client.execute(method);
            responseCode = httpResponse.getStatusLine().getStatusCode();
            content = httpResponse.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(content));
            try {
                responseBody = StreamUtil.readString(reader);
            } finally {
                StreamUtil.close(reader);
            }
        } catch (Exception e) {
            throw new OAuthException(e, "refreshAccessToken failed with Exception: <br>" + e);
        } finally {
            if (method != null) {
                try {
                    if (content != null) {
                        content.close();
                    }
                } catch (IOException e) {
                    throw new OAuthException(e, "refreshAccessToken failed with Exception: <br>" + e);
                }
            }
        }
        if (responseCode != HttpStatus.SC_OK) {
            acquireToken(true, true); // Failed to renew token, get a new one
            return null;
        } else {
            setOAuthData(responseBody);
            renewedtoken = createToken(getAppId(), getServiceName()); // Now create a new token and save that in the store          
            Context context = Context.get();
            setAccessTokenObject(renewedtoken);
            try {
                if (!context.isCurrentUserAnonymous()) {
                    CredentialStore credStore = findCredentialStore();
                    if (credStore != null) {
                        // if the token is already present, and was expired due to which we have fetched a new 
                        // token, then we remove the token from the store first and then add this new token.
                        deleteToken();
                        credStore.store(getServiceName(), ACCESS_TOKEN_STORE_TYPE, getUserId(), token);
                    }
                } else {
                    AnonymousCredentialStore.storeCredentials(context, token, getAppId(), getServiceName()); // Store the token for anonymous user
                }
            } catch (CredentialStoreException cse) {
                throw new OAuthException(cse, "Error trying to renew Token.");
            }
        }
        return renewedtoken;
    }

    public CredentialStore findCredentialStore() throws OAuthException {
        CredentialStore credStore = null;
        try {
            credStore = CredentialStoreFactory.getCredentialStore(getCredentialStore());
        } catch (CredentialStoreException cse) {
            throw new OAuthException(cse, "Error finding credentials from the store");
        }
        return credStore;
    }

    /*
     *  This method starts the Oauth2.0 Dance process. 
     *  1. Make the call to fetch the authorization token.
     *  2. Host server redirect to OA2Callback.
     *  3. OA2Callback would try to fetch the access and refresh tokens.
     *  4. Interceptor from endpoint then takes care of inserting the required security headers 
     */
    public synchronized void performOAuth2Dance() {

        setApplicationPage();
        Context context = Context.get();

        String callbackurl = "";
        try {
            callbackurl = getCallbackUrl(context);
        } catch (OAuthException e1) {
            Platform.getInstance().log(e1);
        }
        setClient_uri(callbackurl);

        // Store the Oauth handler in session object
        context.getSessionMap().put(Configuration.OAUTH2_HANDLER, this);

        Object resp = Context.get().getHttpResponse();
        try {
            Context.get().sendRedirect(getAuthorizationNetworkUrl());
        } catch (Exception e) {
            Platform.getInstance().log(e);
        }
    }

    /*
     * This method sets the reference of page which initiated the secured call.
     * We need this to eventually navigate back to calling page
     */

    public void setApplicationPage() {
        // We just return to the same page
        Object _req = Context.get().getHttpRequest();
        if (_req instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) _req;
            String url = UrlUtil.getRequestUrl(request);
            this.applicationPage = url;
        }
    }

    public String getApplicationPage() {
        return applicationPage;
    }

    public boolean shouldRenewToken() throws OAuthException {
        return shouldRenewToken(null);
    }

    /*
     * This method checks if the active token has expired based on the isvalidupto parameter from OADance,
     * Stored as  Expires parameter in AccessToken
     */
    public boolean shouldRenewToken(AccessToken token) throws OAuthException {
        // We do not automatically renew/acquire it - we just get it from the store
        if (token == null) {
            token = _findTokenFromStore(Context.get(), null);
            if (token == null) {
                throw new OAuthException(null, "No user token is available");
            }
        }
        return token.isExpired(getExpireThreshold());
    }

    public void setExpireThreshold(int expireThreshold) {
        this.expireThreshold = expireThreshold;
    }

    public int getExpireThreshold() {
        return expireThreshold;
    }

    // ==========================================================
    //  Utilities
    // ==========================================================
    /**
     * Read a token from an OAuthResponse
     * @param accessor
     * @param response
     * @return
     * @throws IOException
     * 
     * This method creates a new token
     */
    public AccessToken createToken(String appId, String serviceName) throws OAuthException {
        try {

            long now = System.currentTimeMillis();
            String expirationinterval = getExpiresIn(); // we get the expires interval from server, convert this to a date object
            Date expiresIn = null;
            expiresIn = new Date(now + Long.parseLong(expirationinterval) * 1000);
            return new AccessToken(appId, serviceName, getConsumerKey(), getAccessToken(), getConsumerSecret(),
                    getUserId(), expiresIn, getRefreshToken());
        } catch (Exception e) {
            throw new OAuthException(e);
        }
    }

    @Override
    public String getCallbackUrl(Context context) throws OAuthException {
        Object _req = context.getHttpRequest();
        if (_req instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) _req;
            String proxyBaseUrl = PathUtil.concat(ServiceUtil.getProxyUrl(request), OA2Callback.URL_PATH, '/');
            return proxyBaseUrl;
        }
        return null;
    }

    @Override
    public void doPreAuthorizationFlow() throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void doPostAuthorizationFlow() throws Exception {
        // TODO Auto-generated method stub

    }

    public boolean isForceTrustSSLCertificate() {
        return forceTrustSSLCertificate;
    }

    public void setForceTrustSSLCertificate(boolean forceTrustSSLCertificate) {
        this.forceTrustSSLCertificate = forceTrustSSLCertificate;
    }

}