C# 迁移到OAuth 2.0后获取access_令牌时出现问题

C# 迁移到OAuth 2.0后获取access_令牌时出现问题,c#,facebook,oauth-2.0,C#,Facebook,Oauth 2.0,我已尝试将我的应用程序迁移到OAuth 2.0例程。我无法从JavaScript API设置的cookie中获取access_令牌。我对cookie中的信息进行解码,但得到的不是访问令牌和用户信息,而是代码。这似乎是一个相当奇怪的变化。 是否有解决方法,因为在获取代码时,如果没有指定重定向uri,则似乎无法将代码交换到访问令牌 我曾考虑过从JavaScript API中的响应中获取access_令牌并将其存储在cookie中,但这有点违背了扩展安全性的全部目的,我想问问是否有一种正确的方法来实现

我已尝试将我的应用程序迁移到OAuth 2.0例程。我无法从JavaScript API设置的cookie中获取access_令牌。我对cookie中的信息进行解码,但得到的不是访问令牌和用户信息,而是代码。这似乎是一个相当奇怪的变化。 是否有解决方法,因为在获取代码时,如果没有指定重定向uri,则似乎无法将代码交换到访问令牌

我曾考虑过从JavaScript API中的响应中获取access_令牌并将其存储在cookie中,但这有点违背了扩展安全性的全部目的,我想问问是否有一种正确的方法来实现它

可能是我做错了什么,如果是这样,请告诉我:)

编辑
我知道cookie包含一个已签名的请求,但根据文档,已签名的请求应该包含我所需的信息,如access_token和uid,但在我的实例中,它只包含代码。这基本上是我不理解的部分。

你必须使用代码来获取实际的访问令牌。

fbsr\u应用程序ID cookie实际上是一个签名请求,查看facebook官方文档如何解码签名请求验证签名并获取用户信息。您还可以查看官方的PHPSDK源代码,了解他们是如何从那里获得访问令牌的

不幸的是,我没有直接的答案,但我确实有一个针对facebook的文档错误,我试图在那里获取文档:

我有一个类似的问题,当我尝试从FB.login的authResponse解码signedRequest时,它们的有效负载包含如下内容:

{"algorithm":"HMAC-SHA256","code":"THE_CODE_HERE","issued_at":1315433244,"user_id":"THE_USER_ID"}
正如您所说,文档确实讨论了如何将代码转换为访问令牌。这似乎出现在此处的“服务器端”文档中:

如果您从FB.login获取accessToken,您可以从js获取它并将其缓存,但正如您所说,它实际上并没有签名,并且相对容易被伪造

你是对的,这里似乎没有这里描述的任何有用信息:developers.facebook.com/docs/authentication/signed_request/(http已删除,因为我没有足够的信誉点发布超过2个链接-抱歉)

也许你可以投票支持我的错误?我也将在该bug上发布此链接。

结果表明(尽管没有文档记录),我们需要自己将代码交换为访问令牌。我认为这完全是浪费,因为那是旧饼干的优点。获取访问令牌既快捷又方便

无论如何。要从新cookie中获取访问令牌,您需要执行以下操作:

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());
}
这似乎有点多余,但我想您可以将access_令牌存储在会话变量中。如果你这样做,并且在Facebook上构建你的应用程序,你需要知道,如果用户将浏览器隐私设置设置为中等,那么它在IE 6、7和8中将无法工作。这有一个解决办法,但由于它不是这个问题的一部分,我将不写它。如果人们真的想要它,写一条评论,我会展示它:)

-----------------------------------编辑------------------------------------------

当使用任何旧IE浏览器时,您不能在Iframed中的页面中使用cookie或会话变量,就像您在Facebook上的页面一样。这是一个无法在编码中充分解决的问题。我的意思是,这个解决方案并不好。您需要在响应中设置p3p标题。当然,您可以在为所服务的所有页面编码时执行此操作,但最简单的解决方案(如果您使用.NET服务器托管页面)是为IIS设置p3p策略。有关这方面的指南,请参见。你在p3p策略中写什么并不重要(如果你查看Facebooks自己的,你会发现他们使用“我们没有p3p策略”),重要的是有一些东西。尽管我在使用随机文本时遇到了问题,但如果你在示例中使用文本,应该不会有问题:)


我花了很长时间才发现这一点,所以我希望有人能使用它:D

你显然还没有阅读完整的问题。我写道,当你以这种方式获取代码时,你不能这样做:)我知道这是一个已签名的请求。问题是我没有得到他们在正式文档中指定的输出。根据文档,已签名的请求应该包含我需要的用户信息,但它只包含我实例中的代码,这就是我不理解的地方。@Kasper:这里的示例对你有用吗?不幸的是,我不是真的能够使用php,而是需要使用.NET来实现这一点,我们希望你为会话变量和IFRAME;)谢谢这真的帮助了我。thx这很有效。只是出于好奇,为什么重定向uri是一个空字符串?@EXCENSION很抱歉,但我记不起来了,因为我已经很久没有回答这个问题了。但这就是人们很难让它工作的主要原因:)@EXCENSION关于你的评论“为什么重定向uri是一个空字符串?”“-我认为答案是‘代码’来自facebook会话cookie(签名请求),而不是使用url重定向登录方法。