尝试使用 Graph API Explorer 中生成的访问令牌会产生不正确的权限
Trying to use Access Token generated in the Graph API Explorer yields incorrect permissions
我创建了一个 C# 应用程序,它向 Facebook Graph API 发出 GET/POST 请求,以自动将图像上传到页面时间轴。
该应用程序是一个控制台应用程序,因此就登录 facebook 以检索访问令牌而言,用户登录是不行的,相反,我使用 Graph API 生成令牌,我的应用程序扩展了它.
这工作了大约 12 个小时,直到现在所有权限都是错误的。
当我在 Graph Explorer 中生成令牌时,我 select "manage_pages"、publish_pages" & "publish_actions" 权限。如果使用 Graph Explorer 执行使用密钥获取对 https://graph.facebook.com/v2.3/debug_token
的请求我获得了我 select 编辑的三个权限,外加一个 "public_profile" 权限,一切似乎都很好。
当我 运行 在我的应用程序和 C# 代码中 运行 向 https://graph.facebook.com/v2.3/debug_token
发送一个 GET 请求时,使用我查询时使用的相同访问令牌,但是使用应用程序自己的访问权限它在 运行 时生成的密钥进行身份验证,我获得的唯一权限是 "public_profile",即使对 https://graph.facebook.com/v2.3/" + PageID + "/?fields=can_post
returns 的 GET 请求可以使用访问密钥对于 posting,但是当我尝试 post 时,我得到一个错误,即我缺少我首先 selected 的 3 个关键权限。
发生了什么事?
作为参考,以下是我正在使用的功能;
//THIS IS THE FUNCTION USED TO CHECK IF THE TOKEN IS VALID
static bool checkValidToken(string inputToken)
{
string url = "https://graph.facebook.com/v2.3/debug_token?input_token=" + inputToken + "&access_token=" + getAppAccessToken();
WebRequest wrGETURL = WebRequest.Create(url);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = (JObject)JObject.Parse(jsonResponse).GetValue("data");
return (bool)resonse.GetValue("is_valid");
}
//THIS IS USED TO CHECK IF THE TOKEN CAN BE USED TO POST TO PAGE
static bool checkCanPost(string inputToken)
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/" + PageID + "/?fields=can_post&access_token=" + inputToken);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = (JObject)JObject.Parse(jsonResponse);
return (bool)resonse.GetValue("can_post");
}
//USED TO CALCULATE THE EXPIRY DATE ON THE TOKEN
static DateTime getExpiryDate(string inputToken)
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/debug_token?input_token=" + inputToken + "&access_token=" + getAppAccessToken());
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = (JObject)JObject.Parse(jsonResponse).GetValue("data");
DateTime expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local).AddSeconds((int)resonse.GetValue("expires_at"));
if ((int)resonse.GetValue("expires_at") == 0)
{
expires = DateTime.UtcNow.AddMonths(2);
}
return expires;
}
//USED TO GENERATE THE APP ACCESS TOKEN
static string getAppAccessToken()
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/oauth/access_token?client_id=" + AppID + "&client_secret=" + AppSecret + "&grant_type=client_credentials");
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = JObject.Parse(jsonResponse);
return (string)resonse.GetValue("access_token");
}
//USED TO EXTEND AN EXISTING TOKEN
static string extendToken(string inputToken)
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/oauth/access_token?grant_type=fb_exchange_token&client_id=" + AppID + "&client_secret=" + AppSecret + "&fb_exchange_token=" + inputToken);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = JObject.Parse(jsonResponse);
Console.WriteLine(jsonResponse);
return (string)resonse.GetValue("access_token");
}
//USED TO GENERATE A TOKEN FOR POSTING AS THE PAGE, RATHER THAN TO THE PAGE
static string getPageToken(string inputToken)
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/"+PageID+"?fields=access_token&access_token="+inputToken);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = JObject.Parse(jsonResponse);
return (string)resonse.GetValue("access_token");
}
//FUNCTION FOR GETTING ALL PERMISSIONS FOR A TOKEN
static List<string> getTokenPermissions(string inputToken)
{
string url = "https://graph.facebook.com/v2.3/debug_token?input_token=" + inputToken + "&access_token=" + getAppAccessToken();
WebRequest wrGETURL = WebRequest.Create(url);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = (JObject)JObject.Parse(jsonResponse).GetValue("data");
JToken scopes = resonse.GetValue("scopes");
List<string> returnList = new List<string>();
foreach (JToken tokrow in scopes)
{
returnList.Add((string)tokrow);
}
return returnList;
}
//DEBUG FUNCTION FOR OUTPUTTING ALL OF A TOKENS USER/PAGE PERMISSIONS
static void outputPermissions(string theToken)
{
List<string> userPermissions = getTokenPermissions(theToken);
List<string> appPermissions = getTokenPermissions(getPageToken(theToken));
Console.WriteLine("USER:");
foreach (string perm in userPermissions)
{
Console.WriteLine(perm);
}
Console.WriteLine("APP:");
foreach (string perm in appPermissions)
{
Console.WriteLine(perm);
}
Console.Read();
}
// FUNCTION THAT ACTUALLY POSTS TO THE PAGE
static async Task PostHandler(Post toPost,string theToken)
{
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{ "url", toPost.ImageURL },
{"access_token",getPageToken(theToken)},
{"caption",toPost.Caption}
};
Console.WriteLine("Image we are uploading is " + toPost.ImageURL);
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://graph.facebook.com/v2.3/" + PageID + "/photos", content);
Console.WriteLine("Uploaded!");
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
Console.Read();
JObject resonse = JObject.Parse(responseString);
}
}
当 post 运行 它 returns
error #200 Requires extended permission: (manage_pages and pubish_pages) or (manage_pages and publish_actions)
问题中的错误实际上是 Facebook 团队引入的错误,不幸的是恰好与我的应用程序测试同时发生,因为发布错误已被记录并更正。
找到更多信息
我创建了一个 C# 应用程序,它向 Facebook Graph API 发出 GET/POST 请求,以自动将图像上传到页面时间轴。
该应用程序是一个控制台应用程序,因此就登录 facebook 以检索访问令牌而言,用户登录是不行的,相反,我使用 Graph API 生成令牌,我的应用程序扩展了它. 这工作了大约 12 个小时,直到现在所有权限都是错误的。
当我在 Graph Explorer 中生成令牌时,我 select "manage_pages"、publish_pages" & "publish_actions" 权限。如果使用 Graph Explorer 执行使用密钥获取对 https://graph.facebook.com/v2.3/debug_token
的请求我获得了我 select 编辑的三个权限,外加一个 "public_profile" 权限,一切似乎都很好。
当我 运行 在我的应用程序和 C# 代码中 运行 向 https://graph.facebook.com/v2.3/debug_token
发送一个 GET 请求时,使用我查询时使用的相同访问令牌,但是使用应用程序自己的访问权限它在 运行 时生成的密钥进行身份验证,我获得的唯一权限是 "public_profile",即使对 https://graph.facebook.com/v2.3/" + PageID + "/?fields=can_post
returns 的 GET 请求可以使用访问密钥对于 posting,但是当我尝试 post 时,我得到一个错误,即我缺少我首先 selected 的 3 个关键权限。
发生了什么事?
作为参考,以下是我正在使用的功能;
//THIS IS THE FUNCTION USED TO CHECK IF THE TOKEN IS VALID
static bool checkValidToken(string inputToken)
{
string url = "https://graph.facebook.com/v2.3/debug_token?input_token=" + inputToken + "&access_token=" + getAppAccessToken();
WebRequest wrGETURL = WebRequest.Create(url);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = (JObject)JObject.Parse(jsonResponse).GetValue("data");
return (bool)resonse.GetValue("is_valid");
}
//THIS IS USED TO CHECK IF THE TOKEN CAN BE USED TO POST TO PAGE
static bool checkCanPost(string inputToken)
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/" + PageID + "/?fields=can_post&access_token=" + inputToken);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = (JObject)JObject.Parse(jsonResponse);
return (bool)resonse.GetValue("can_post");
}
//USED TO CALCULATE THE EXPIRY DATE ON THE TOKEN
static DateTime getExpiryDate(string inputToken)
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/debug_token?input_token=" + inputToken + "&access_token=" + getAppAccessToken());
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = (JObject)JObject.Parse(jsonResponse).GetValue("data");
DateTime expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local).AddSeconds((int)resonse.GetValue("expires_at"));
if ((int)resonse.GetValue("expires_at") == 0)
{
expires = DateTime.UtcNow.AddMonths(2);
}
return expires;
}
//USED TO GENERATE THE APP ACCESS TOKEN
static string getAppAccessToken()
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/oauth/access_token?client_id=" + AppID + "&client_secret=" + AppSecret + "&grant_type=client_credentials");
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = JObject.Parse(jsonResponse);
return (string)resonse.GetValue("access_token");
}
//USED TO EXTEND AN EXISTING TOKEN
static string extendToken(string inputToken)
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/oauth/access_token?grant_type=fb_exchange_token&client_id=" + AppID + "&client_secret=" + AppSecret + "&fb_exchange_token=" + inputToken);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = JObject.Parse(jsonResponse);
Console.WriteLine(jsonResponse);
return (string)resonse.GetValue("access_token");
}
//USED TO GENERATE A TOKEN FOR POSTING AS THE PAGE, RATHER THAN TO THE PAGE
static string getPageToken(string inputToken)
{
WebRequest wrGETURL = WebRequest.Create("https://graph.facebook.com/v2.3/"+PageID+"?fields=access_token&access_token="+inputToken);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = JObject.Parse(jsonResponse);
return (string)resonse.GetValue("access_token");
}
//FUNCTION FOR GETTING ALL PERMISSIONS FOR A TOKEN
static List<string> getTokenPermissions(string inputToken)
{
string url = "https://graph.facebook.com/v2.3/debug_token?input_token=" + inputToken + "&access_token=" + getAppAccessToken();
WebRequest wrGETURL = WebRequest.Create(url);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string jsonResponse = objReader.ReadToEnd();
JObject resonse = (JObject)JObject.Parse(jsonResponse).GetValue("data");
JToken scopes = resonse.GetValue("scopes");
List<string> returnList = new List<string>();
foreach (JToken tokrow in scopes)
{
returnList.Add((string)tokrow);
}
return returnList;
}
//DEBUG FUNCTION FOR OUTPUTTING ALL OF A TOKENS USER/PAGE PERMISSIONS
static void outputPermissions(string theToken)
{
List<string> userPermissions = getTokenPermissions(theToken);
List<string> appPermissions = getTokenPermissions(getPageToken(theToken));
Console.WriteLine("USER:");
foreach (string perm in userPermissions)
{
Console.WriteLine(perm);
}
Console.WriteLine("APP:");
foreach (string perm in appPermissions)
{
Console.WriteLine(perm);
}
Console.Read();
}
// FUNCTION THAT ACTUALLY POSTS TO THE PAGE
static async Task PostHandler(Post toPost,string theToken)
{
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{ "url", toPost.ImageURL },
{"access_token",getPageToken(theToken)},
{"caption",toPost.Caption}
};
Console.WriteLine("Image we are uploading is " + toPost.ImageURL);
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://graph.facebook.com/v2.3/" + PageID + "/photos", content);
Console.WriteLine("Uploaded!");
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
Console.Read();
JObject resonse = JObject.Parse(responseString);
}
}
当 post 运行 它 returns
error #200 Requires extended permission: (manage_pages and pubish_pages) or (manage_pages and publish_actions)
问题中的错误实际上是 Facebook 团队引入的错误,不幸的是恰好与我的应用程序测试同时发生,因为发布错误已被记录并更正。
找到更多信息