如果已经授权的用户现在需要更多权限,如何在画布应用程序的signed_request中获取access_token?

发布于 2024-12-27 02:59:47 字数 1552 浏览 1 评论 0原文

让我们假设画布应用程序出现以下情况:

i) 第 1 天: - Facebook 应用程序已创建,需要 read_stream、publish_stream、offline_access 权限。当一个 用户首次访问应用,authorize 调用会重定向用户 到权限允许/拒绝屏幕,并且当用户允许时 将用户重定向回画布 url。

画布 url 在其请求中的签名请求中有 access_token 然后可用于运行应用程序的参数。

下次访问该应用程序的同一用户不需要权限对话框 时间,因为signed_request包含access_token(如果用户有) 过去授权过该应用程序。

代码如下所示:

if(access_token received from signed request)
// do something with user information
else
// redirect user for authorization flow

ii) 第 2 天: - 现在,假设我想在我的列表中再添加一项权限,user_birthdayread_stream、publish_stream、offline_access、user_birthday` 现在下面的逻辑会出现问题,

  if(access_token received from signed request)
    // do something with user information  <-- the access_token does not have new permission
    else
    // redirect user for authorization flow

如何有效地解决这个额外的权限添加问题,因为 API 调用 影响应用程序的性能? 我不想使用类似的东西:

https://graph.facebook.com/me/permissions?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

每次加载应用程序时检查与令牌相关的权限。

更新:

分享一个好方法: 将权限集与接收到的 access_token 一起存储。 例如。如果当前权限是“basic_details-birthday-publish”(我们称之为 1), 将 access_token 和权限集存储为

user  | access_token  | perm_set
Dhruv      sdfsdfsdf       1

现在,在您的设置中,每当您需要请求新权限时,创建一个新权限集“basic_details-birthday-publish-checkins”(我们称之为 2),

然后您需要显示权限对话框仅适用于具有 perm_set = 1 的访问令牌的用户,而不适用于已经具有 perm_set = 2 的用户,这将消除检查每个用户的 access_token 的需要“/me/权限”API。

Let's assume the following situation for a canvas app:

i) day 1:
- Facebook app is created which needs
read_stream,publish_stream,offline_access permissions. When a
user comes to app for first time, authorize call redirects the user
to a permission ALLOW / DENY screen , and when the user allows it
redirects the user back to canvas url.

The canvas url has access_token in a signed request in its request
parameters which can then be used to run the app.

No permission dialog is needed for same user coming to the app next
time, as signed_request contains acess_token if the user had
authorized the app in past.

The code looks like:

if(access_token received from signed request)
// do something with user information
else
// redirect user for authorization flow

ii) day 2: - Now, let's say I want to add one more permission to my list, user_birthday
read_stream,publish_stream,offline_access,user_birthday`
Now the following logic will have problems

  if(access_token received from signed request)
    // do something with user information  <-- the access_token does not have new permission
    else
    // redirect user for authorization flow

How can this additional permission addition be tackled efficiently, as API calls
affect the performance of the app?
I would not want to use something like :

https://graph.facebook.com/me/permissions?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Every time the application loads to check the permissions related to the token.

UPDATE:

Sharing a good method :
Store the permission set along with the access_token with which it was received.
eg. If current permissions are "basic_details-birthday-publish" (lets call it 1),
store the access_token and permission set as

user  | access_token  | perm_set
Dhruv      sdfsdfsdf       1

Now,in your settings, whenever you need to ask for a new permission, create a new permission set "basic_details-birthday-publish-checkins" (lets call it 2),

then you need to show the permissions dialog only for users who have access token with perm_set = 1 and not for users who already have perm_set = 2, this will get rid of the need to check access_token of each user with "/me/permissions" api.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

风柔一江水 2025-01-03 02:59:47

这将是一个两步过程:

  1. 通过向图形路径“/me/permissions”发出请求来检查用户

  2. 如果用户没有授予您所有必需的权限,您需要执行通常的允许/拒绝过程,但这次将新权限添加到“范围” " 参数。

编辑_:我知道验证权限的唯一可靠方法是调用 /me/permissions。

It would be a 2 step process:

  1. Check if the user granted you all required permissions by issuing a request to the Graph path "/me/permissions"

  2. If the user did not grant you all required permissions you need to go through the usual Allow/Deny process but this time with the new permission(s) added to the "scope" parameter.

Edit_: The only reliable way I know to verify permissions is by calling /me/permissions.

哥,最终变帅啦 2025-01-03 02:59:47

好吧,最有效的解决方案需要@Jeff 建议的加上使用实时 API。
第 1 步:创建一个权限表来存储用户首次“连接”到您的应用时的用户权限。
第 2 步: 订阅权限对象,示例:

<?php
require '../src/facebook.php';

$facebook = new Facebook(array(
  'appId'  => 'APP_ID',
  'secret' => 'APP_SECRET',
));

$app = get_app_access_token("APP_ID", "APP_SECRET");
parse_str($app);

$realtime_params = array(
    'object'=>'permissions',
    'fields'=>'read_stream,publish_stream', // most recent permissions required by your app
    'callback_url'=>'CALLBACK_URL_HERE',
    'verify_token'=>'STRING_THAT_SHOULD_BE_PRESENT_IN_THE_CALLBACK_PAGE_TOO',
    'access_token'=>$access_token
);

try {
$res = $facebook->api("/APP_ID/subscriptions", "post", $realtime_params);
} catch (FacebookApiException $e) {
echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
}
function get_app_access_token($id,$secret) { 
    $token_url =    "https://graph.facebook.com/oauth/access_token?" .
                    "client_id=" . $id .
                    "&client_secret=" . $secret .
                    "&grant_type=client_credentials";
    return file_get_contents($token_url);
}

有关此内容的更多信息,请参阅 实时更新文档。

第 3 步:如果用户撤销其中一项权限(例如删除 publish_stream 权限),您的回调页面应该处理 Facebook 发送的 post 请求;在这种情况下,Facebook 会向您发送类似的内容(解码请求后,请参阅 此处):

Array
(
    [object] => permissions
    [entry] => Array
        (
            [0] => Array
                (
                    [uid] => 100003355152933
                    [id] => 100003355152933
                    [time] => 1327005647
                    [changed_fields] => Array
                        (
                            [0] => publish_stream
                        )

                )

        )

)

无论发生了什么更改,我都会使用上述请求作为触发器,查询/user_id/permissions连接并更新权限表。

现在有两种情况:

if(access_token received from signed request)
    if(permissions from table are full)
        // do something with user information
    else
        // ask for missing permission and update permissions table
else
    // redirect user for authorization flow
    // upon full authorization, save to the permissions table too

显然也应该使用其他答案中所说的内容。您应该始终使用“try...catch”子句并检查与权限相关的错误并采取行动!

Well, the most efficient solution would require what @Jeff suggested plus using the Real-time API.
STEP 1: Create a permissions table to store the user permissions when a user "connects" to your app the first time.
STEP 2: subscribe to the permissions object, example:

<?php
require '../src/facebook.php';

$facebook = new Facebook(array(
  'appId'  => 'APP_ID',
  'secret' => 'APP_SECRET',
));

$app = get_app_access_token("APP_ID", "APP_SECRET");
parse_str($app);

$realtime_params = array(
    'object'=>'permissions',
    'fields'=>'read_stream,publish_stream', // most recent permissions required by your app
    'callback_url'=>'CALLBACK_URL_HERE',
    'verify_token'=>'STRING_THAT_SHOULD_BE_PRESENT_IN_THE_CALLBACK_PAGE_TOO',
    'access_token'=>$access_token
);

try {
$res = $facebook->api("/APP_ID/subscriptions", "post", $realtime_params);
} catch (FacebookApiException $e) {
echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
}
function get_app_access_token($id,$secret) { 
    $token_url =    "https://graph.facebook.com/oauth/access_token?" .
                    "client_id=" . $id .
                    "&client_secret=" . $secret .
                    "&grant_type=client_credentials";
    return file_get_contents($token_url);
}

More about this in the Real-time Updates documentation.

STEP 3: Your callback page should handle the post request sent by Facebook, if a user revoked one of the permissions (for example removed the publish_stream permission); in that case, Facebook will send you something like (after decoding the request, see here):

Array
(
    [object] => permissions
    [entry] => Array
        (
            [0] => Array
                (
                    [uid] => 100003355152933
                    [id] => 100003355152933
                    [time] => 1327005647
                    [changed_fields] => Array
                        (
                            [0] => publish_stream
                        )

                )

        )

)

Regardless of what have been changed, I would use the above request as a trigger, query /user_id/permissions connection and update the permissions table.

Now you have two cases:

if(access_token received from signed request)
    if(permissions from table are full)
        // do something with user information
    else
        // ask for missing permission and update permissions table
else
    // redirect user for authorization flow
    // upon full authorization, save to the permissions table too

Obviously what have been said in other answers should be used too. You should always use "try...catch" clauses and check for permission related errors and act upon that!

毁虫ゝ 2025-01-03 02:59:47

你有三种选择,其中之一就是你已经说过你不想做的。

  1. 检查 me/permissions 并循环查看是否所有这些都仍然存在。

  2. 尝试/捕获每个 API 调用并观察收到的错误(请参阅 http://fbdevwiki.com/wiki/ Error_codes),查看是否为 #10 API_EC_PERMISSION_DENIED。如果是这样,则再次向用户请求权限。

  3. 编写您的应用程序,使其向后兼容旧的权限集,这样只有其中的新功能才会向授予新权限的用户显示。当然,您需要尝试/捕获每个 API 调用,以找出需要隐藏/显示应用程序的哪些部分。

You have three choices and one of them is the one you already said you don't want to do.

  1. Check me/permissions and loop thru to see if all of them are still there.

  2. try/catch every API call and watch for the error received (see http://fbdevwiki.com/wiki/Error_codes) to see if it is #10 API_EC_PERMISSION_DENIED. If so, then ask the user for permissions again.

  3. Write your app so it is backwards compatible with the old permission set, so only the new functionality in it appears for the user's who've granted the newer permissions. Of course you will need to try/catch every API call to find out what parts of your app you need to hide/show.
要走就滚别墨迹 2025-01-03 02:59:47

首先,我将陈述显而易见的事情。您应该使用 /me/permissions 端点。这是确定访问令牌是否有效以及是否具有您需要/想要的所有权限的唯一方法。既然您说您想要一个不会在每次加载应用程序时都到达此端点的解决方案,那么我将继续。

我能想到的不检查 /me/permissions API 调用的唯一方法是使用一个将 user_id 映射到用户权限的简单表来跟踪您自己的服务器上的权限。当新用户被授权时,您可以在数据库表中添加一行以获取该 fb 用户 ID 以及他们已授权的权限列表。现在,当他们回来时,您可以获取signed_request并在表中查找他们是否拥有您想要的所有权限。如果他们不这样做,您将提示他们授权额外的权限,并在他们授予您这些权限时更新您的表。

由于您已经要求离线访问,我假设您无论如何都将访问令牌存储在某个地方,因此添加另一个表来获取访问令牌的权限列表似乎不会造成太大的额外负担。

这种设计存在一些明显的缺陷(与 FB 不一致),但如果您的主要目标是避免 /me/permissions 端点,那么这应该适合您。

First, I'll state the obvious. You should use the /me/permissions endpoint. It's the only way to know for sure if the access token is valid and has all of the permissions you need/want. Since you said you want a solution that doesn't hit this endpoint every time the app is loaded, I'll move on.

The only way I can think of to not check the /me/permissions API call is to keep track of the permissions on your own server with a simple table mapping user_id to the permissions for the user. When a new user is authorized, you add a row to your database table for that fb user id and the list of permissions they've authorized. Now when they come back, you can get the signed_request and lookup in your table whether they have all the permissions you want. If they don't, you prompt them to authorize the additional permissions and update your table if they grant you those permissions.

Since you're already asking for offline_access, I assume you're storing the access tokens somewhere anyway, so adding another table for a list of permissions on the access token seems like it wouldn't be too much of an additional burden.

There are some obvious pitfalls with this design (inconsistency with FB), but if your primary objective is to avoid the /me/permissions endpoint, then this should work for you.

随遇而安 2025-01-03 02:59:47

不要忘记您还可以使用 javascript SDK 来提示权限。 javascript SDK 实际上内联完成了所有事情。您可以使用所需的权限参数调用“登录”函数,如果它们已经被授予,则不会发生任何情况。

正如其他人所建议的,您可以查询图表中的 /me/permissions,但使用 javascript api 方法来获取信息。因此,如果您不想存储用户授予的权限,并订阅实时更新 api 以确保它们保持最新状态,您可以使用 javascript api 从客户端内联执行所有操作。

您几乎消除了服务器扮演的任何角色,并通过 JavaScript 将用户直接链接到 Facebook。 Facebook 实际上在客户端做了一些缓存,因此调用可能是即时的。

这是一篇关于提示缺少权限的 Facebook 博客文章。
https://developers.facebook.com/blog/post/576/

Don't forget you can also use the javascript SDK to prompt for permissions. The javascript SDK actually does everything inline. You can call the "login" function with the permissions parameters that you need, if they are already granted, nothing happens.

As others suggested, you can query the graph for /me/permissions, but use the javascript api method to get the information. So if you don't want to store the permissions the user granted, and subscribe to the real time update api to make sure they stay up to date, you can use the javascript api to do everything inline, from the client side.

You're pretty much eliminating your server from playing any role and linking the user directly to Facebook via javascript. Facebook actually does some caching on the client side so the calls may be instantaneous.

Here is a Facebook blog post about prompting for missing permissions.
https://developers.facebook.com/blog/post/576/

鲜血染红嫁衣 2025-01-03 02:59:47

这里的所有答案都基于旧的 facebook auth 系统,其中,当没有有效的signed_request 参数时,您将用户重定向到 oauth url,其中范围参数包含您所需的权限。

如果没有请求离线访问权限,那么没有问题,因为每个用户访问令牌将在两个小时内失效,因此在使用新权限更改范围参数两个小时后,每次新访问都会被重定向到带有新权限的oauth页面范围,所以 facebook 会正确处理它。

由于您已经获取了离线权限并且您需要它,那么用户的访问令牌将不会轻易失效(如果只有用户更改密码,或停用您的应用程序),前述解决方案将无法正常工作,

我接受检查图中的权限错误api 调用是一种检查用户是否不允许您请求的方法,然后重定向用户以让他或她向您授予您的权限。这是可以接受的,但没有必要

因为现在,您可以在 facebook 应用程序设置页面中设置所需的权限,更具体地说,

请转到 https: //developers.facebook.com/

并选择您的应用程序。

点击设置->左侧菜单中的“身份验证对话框”选项卡。
并选择您必须的权限,这将允许所有用户肯定会以所需的权限访问您的页面,

但是,您不能在此处强制执行任何扩展权限。

因此,解决您的问题的唯一可能的答案是,立即删除所有访问令牌,因为这将允许所有返回的用户重定向到新的权限对话框。

但这个解决方案将使您无法获取有关用户群的信息,
为了克服这个问题,您只能在用户访问您的页面时触发此问题,因此在删除他或她的访问令牌后,用户可能会重新访问您的页面。但是您必须为每个用户保留额外的位,以确保他们是否受到此访问令牌删除操作的影响。如果用户没有进行此操作并访问您的应用程序,只需删除访问令牌并将用户重定向到具有新权限的oauth页面,如果用户已经这样做了,那么这种事情就没有问题。

所以我的答案是上面的替代方案。但解决此问题的最困难和最优雅的方法是,仅在用户与您的应用程序交互时才请求权限,以使用您的应用程序需要我们讨论的权限的功能。这样,oauth 对话框的 CTR 率就会上升,因为您不会让用户担心您请求的初始权限的长度。用户将更乐意使用您的应用程序。每当他们需要在您的应用程序中做出色的事情时,您都可以善意地请求获得出色的许可。

祝你好运

All answers here are based on the older facebook auth system, in which, when there is not a valid signed_request parameter, you redirect user to oauth url, with the scope parameter containing the permissions you require.

If no offline access permission is requested, then there is no problem since every user access token will be invalid in two hours, so after two hours of changing the scope parameter with new permissions, every new visit, will be redirected to oauth page with new scope, so facebook will handle it correctly.

Since you already took offline permissions and you need it, then accesstokens of users will not be easily invalitated(if only user changes password, or deactivates your app), the preceeding solution will not work correctly,

I accept that checking for permission errors in graph api calls, is a way to check wheather a user does not permitted you what you have asked for then redirect user to let him or her garant you your permissions. It is acceptable, but unneccessary

Because now, you can make your required permissions in the facebook app settings page, more specifically

go to https://developers.facebook.com/

and choose your app.

click settings -> Auth Dialog tab in the left menu.
and choose your must permissions, that will allow all users are for sure, will come to your page with required permissions,

However, you cannot make any extended permission here mandotory.

So the only possible answer to your problem is, delete all your access tokens at once, as that will allow all returning users to be redirected to the new permission dialog.

But this solution will render you helples about getting information about your user base,
to overcame this problem, you can only trigger this when a user visits your page, so after deleting his or her access tokeni user will probably revisit your page. But you have to keep an extra bit for every user, holding that wheather they are subjected to this access token deletion operation. If user is not subjected to this operation and visits your app, just delete the access token and redirect the user to oauth page with new permissions, if user already did it, then there is no problem for this kind of thing.

So my answer is the above alternatives. But the hardest and elegant way to this problem is, only ask for permissions whenever user interacts with your app to use that functionality of your app that requires the permission we talk about. That way, the oauth dialog CTR rate will go up since you will not make your user afraid of the length of the initial permissions that you ask for. Users will be more content about using your app. Whenever they need to do wonderfull things in your app, you can then ask kindly for a wonderfull permission.

good luck

无力看清 2025-01-03 02:59:47

实施建议。

将权限集与接收到的 access_token 一起存储。
例如。如果当前权限是“basic_details-birthday-publish”(我们称之为 1),
将 access_token 和权限集存储为

user  | access_token  | perm_set
Dhruv      sdfsdfsdf       1

现在,在您的设置中,每当您需要请求新权限时,创建一个新权限集“basic_details-birthday-publish-checkins”(我们称之为 2),

然后您需要显示权限对话框仅适用于具有 perm_set = 1 的访问令牌的用户,而不适用于已经具有 perm_set = 2 的用户,这将消除检查每个用户的 access_token 的需要“/me/权限”API。

An implementation suggestion.

Store the permission set along with the access_token with which it was received.
eg. If current permissions are "basic_details-birthday-publish" (lets call it 1),
store the access_token and permission set as

user  | access_token  | perm_set
Dhruv      sdfsdfsdf       1

Now,in your settings, whenever you need to ask for a new permission, create a new permission set "basic_details-birthday-publish-checkins" (lets call it 2),

then you need to show the permissions dialog only for users who have access token with perm_set = 1 and not for users who already have perm_set = 2, this will get rid of the need to check access_token of each user with "/me/permissions" api.

萌酱 2025-01-03 02:59:47
$facebook = new Facebook(array(
                'appId' => 'xxxxxx',
                'secret' => 'xxxxx',
                'cookie' => true,
            ));
$code = @$_REQUEST["code"];//only get after log in into the app
if(empty($code)) 
{
$dialog_url     = "http://www.facebook.com/dialog/oauth?client_id=" 
                . $app_id . "&redirect_uri=" .  urlencode($canvas_page_url)."&scope=email,read_requests,offline_access,read_mailbox,user_relationships,user_likes,user_online_presence,user_activities,user_status,user_groups,manage_pages,friends_status,read_stream,friends_photos,publish_stream";
 echo("<script> top.location.href='" . $dialog_url . "'</script>");
}
 $token_url         = "https://graph.facebook.com/oauth/access_token?client_id="
                . $app_id . "&redirect_uri=" . urlencode($canvas_page) . "&client_secret="
                . $app_secret . "&code=" . $code;
$access_token   = @file_get_contents($token_url);

尝试使用上面的代码并重新加载应用程序,然后它将显示一个弹出窗口以访问您添加的额外权限。

$facebook = new Facebook(array(
                'appId' => 'xxxxxx',
                'secret' => 'xxxxx',
                'cookie' => true,
            ));
$code = @$_REQUEST["code"];//only get after log in into the app
if(empty($code)) 
{
$dialog_url     = "http://www.facebook.com/dialog/oauth?client_id=" 
                . $app_id . "&redirect_uri=" .  urlencode($canvas_page_url)."&scope=email,read_requests,offline_access,read_mailbox,user_relationships,user_likes,user_online_presence,user_activities,user_status,user_groups,manage_pages,friends_status,read_stream,friends_photos,publish_stream";
 echo("<script> top.location.href='" . $dialog_url . "'</script>");
}
 $token_url         = "https://graph.facebook.com/oauth/access_token?client_id="
                . $app_id . "&redirect_uri=" . urlencode($canvas_page) . "&client_secret="
                . $app_secret . "&code=" . $code;
$access_token   = @file_get_contents($token_url);

try with above code and reload the app ,then it will show a pop up to get access to extra permissions you add.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文