开发者

Problem getting access_token after migrating to OAuth 2.0

I have tried migrating my app to the OAuth 2.0 routine. I am having trouble getting the access_token from the cookie set by the JavaScript API. I decode the information in the cookie, but instead of an access_token and the user information I get a code. This seems like a rather weird change. Is there any workaround for this, because it seems that you can't get your code exchanged to an access_token when you haven't specified a redirect_uri when you acquired the code.

I have considered just taking the access_token from the re开发者_JAVA技巧sponse in the JavaScript API and storing it in a cookie, but that kinda defeats the whole purpose of the extended security and I wanted to ask if there was a proper way to do it.

Could be that I am doing something wrong though, and if that is the case please tell me :)

EDIT I am aware that the cookie holds a signed request, but according to the docs that signed request should hold the information I require like access_token and uid, but in my instance it only holds the code. That is basically the part I don't understand.


Turns out that (even though it is not documented) we need to exchange the code for an access_token ourselves. I think this is a total waste since that was the nice thing about the old cookie. It was fast and easy to get the access_token.

Anyway. To get the access_token from the new cookie you need to do the following:

public string ReturnAccessToken()
{
    HttpCookie cookie = htc.Request.Cookies[string.Format("fbsr_{0}", facebookAppID)];
    string jsoncode = System.Text.ASCIIEncoding.ASCII.GetString(FromBase64ForUrlString(cookie.Value.Split(new char[] { '.' })[1]));

    JsonData data = JsonMapper.ToObject(jsoncode);

    getAccessToken(data["code"].ToJson()
}

private string getAccessToken(string code)
{
    //Notice the empty redirect_uri! And the replace on the code we get from the cookie.
    string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}", "YOUR_APP_ID", "", "YOUR_APP_SECRET", code.Replace("\"", ""));

    System.Net.HttpWebRequest request = System.Net.WebRequest.Create(url) as System.Net.HttpWebRequest;
    System.Net.HttpWebResponse response = null;

    using (response = request.GetResponse() as System.Net.HttpWebResponse)
    {
        System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream());

        string retVal = reader.ReadToEnd();
        return retVal;
    }
}

public byte[] FromBase64ForUrlString(string base64ForUrlInput)
{
    int padChars = (base64ForUrlInput.Length % 4) == 0 ? 0 : (4 - (base64ForUrlInput.Length % 4));
    StringBuilder result = new StringBuilder(base64ForUrlInput, base64ForUrlInput.Length + padChars);
    result.Append(String.Empty.PadRight(padChars, '='));
    result.Replace('-', '+');
    result.Replace('_', '/');
    return Convert.FromBase64String(result.ToString());
}

This may seem a bit redundant, but I suppose you can store the access_token in a session variable. If you do this and iFrame the your app on Facebook you need to know that it will not work in IE 6, 7 and 8 if the user have set his browser privacy settings to medium. There is a workaround for this, but as it is not a part of this question I will not write it. If people really want it, write a comment and I will show it :)

-----------------------------------EDIT------------------------------------------

When using any of the old IE browsers you can't use cookies or session variables in pages that are Iframed in, like your pages on Facebook. This is a problem that can't really be solved sufficiently in coding. By sufficiently I mean that the solution is not nice. You need to set the p3p-header in your response. You can of course do this in coding for all the pages that you service, but the easiest solution (if you are using a .NET server to host your pages) is to set up a p3p policy for the IIS. A guide for this can be seen in http://support.microsoft.com/kb/324013. It shouldn't matter what you write in the p3p policy (if you check Facebooks own you can see that they use "We don't have a p3p policy), the important part is that there stands something. I have had troubles just using random text though, but if you use the text in the example there shouldn't be a problem :)

This took me forever to find out, so I hope someone can use it :D


Unfortunately I don't have the answer directly, but I do have a documentation bug that I filed against facebook in order to try to get the documentation there: http://bugs.developers.facebook.net/show_bug.cgi?id=20363

I have a similar problem that when I try to decode the signedRequest from the authResponse of FB.login, they payload contains something like:

{"algorithm":"HMAC-SHA256","code":"THE_CODE_HERE","issued_at":1315433244,"user_id":"THE_USER_ID"}

As you stated, the docs do talk about how to turn that code into an access_token. That appears to be in the "Server Side" documentation here: http://developers.facebook.com/docs/authentication/

If you grab the accessToken from FB.login you can get it from the js and cache it, but as you said, that isn't actually signed, and could relatively easily be faked.

And you're right, this doesn't appear to have any of the useful information that's described here: developers.facebook.com/docs/authentication/signed_request/ (http removed since I don't have enough reputation points yet to post more than 2 links - sorry)

Perhaps you can vote up my bug? I'll post this link on that bug too.


fbsr_APP_ID cookie is actually a signed_request, check out facebook official docs how do you decode signed request verify signature and get the user information. You can look also at official php SDK source how they get access token from there.


You have to use the code to get the actual access_token.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜