Requesting long lived access_token on serverside f

2019-08-16 22:18发布

问题:

I have a Java web app that posts items to our users facebook walls, when the user initially signs up we get a 60 day access_token which is persisted to our database, now that the offline_access is be removed I using our 'Login with facebook' button to update the tokens when the user logs into our website, this is all good as they will typically visit more than 60 days apart.

I have implemented the above and it works well...but then I found that the access tokens that are being generated from the login action expire after 1 hour....obviously not good a we cant post to their walls while they are away.

The code below demonstrates how we are getting the tokens via the signed_request method (in Java SEAM App), this works ok, but the tokens are short-lived

Can anyone suggest how to ensure the tokens are the 60-day type

Thanks

public void loginWithFacebook(){
    accessToken = null;
    try {
        accessToken = FaceBookSecurity.getFBAccessToken();
    } catch (Exception e) {
        log.error("Error getting FB access token: "+e);
    }
    FacebookClient facebookClient = new DefaultFacebookClient(accessToken);
    com.restfb.types.User facebookUser = facebookClient.fetchObject("me", com.restfb.types.User.class);
    facebookEmail = facebookUser.getEmail();
    if (facebookEmail != null) {
        new RunAsOperation(true) {
            public void execute() {
                user = ((UserDAO)Component.getInstance("userDAO")).findByEmail(StringUtils.lowerCase(facebookEmail));
                if (user != null && user.getFacebookToken() != null && !accessToken.equals(user.getFacebookToken())) {
                    user.setFacebookToken(accessToken);
                    log.error("FB: updating "+user.getFirstname()+" "+user.getSurname()+"s FB token to: "+accessToken);
                }
            }
        }.run();
        if (user != null) {
            //set the user as logged in

            return;
        }
    }
    messagePoster.postPopupErrorMessage(messages.get("facebookLoginFailed"));
}

public static String getFBAccessToken()
        throws Exception {

    HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    Cookie fbCookie = getFBCookie(request);

    String fbCookieValue = fbCookie.getValue();
    String[] stringArgs = fbCookieValue.split("\\.");
    String encodedPayload = stringArgs[1];
    JsonObject data;
    try{
        String payload = base64UrlDecode(encodedPayload);

        // gets the js object from the cookie
        data = new JsonObject(payload);
    }catch (Exception e){
        return "";
    }

    String authUrl = getAuthURL(data.getString("code"));
    URL url = new URL(authUrl);
    URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(),
            url.getQuery(), null);
    String result = readURL(uri.toURL());

    String[] resultSplited = result.split("&");
    return resultSplited[0].split("=")[1];
}

// creates the url for calling to oauth.
public static String getAuthURL(String authCode) {
    String url = "https://graph.facebook.com/oauth/access_token?client_id="
            + FacebookApp.appId
            + "&redirect_uri=&client_secret="
            + FacebookApp.appSecret + "&code="
            + authCode;
    return url;
}

// reads the url.
private static String readURL(URL url) throws IOException {
    InputStream is = url.openStream();
    InputStreamReader inStreamReader = new InputStreamReader(is);
    BufferedReader reader = new BufferedReader(inStreamReader);
    String s = "";
    int r;
    while ((r = is.read()) != -1) {
        s = reader.readLine();
    }
    reader.close();
    return s;
}

private static String base64UrlDecode(String input){
    return new String(Base64.decodeBase64(input.getBytes()));
}

回答1:

If all you need is to post to the user's wall, then you can also use app_access_token provided you have asked for publish_stream permission.

You can call :

https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID
&client_secret=YOUR_APP_SECRET
&grant_type=client_credentials

Read this.

Edit: app access_tokens do not expire until the app secret is reset.