Facebook messenger account linking, how to use it? - javascript

There are 4 easy steps described in the documentation about account linking for the messenger platform:
Register a callback URL using Log In Button.
Messenger Platform invokes the registered URL when a user starts the account linking flow. The redirect_uri and account_linking_token parameters are appended to your registered callback.
Once linking is complete, redirect users to the location provided by redirect_uri and append a authorization_code parameter (defined by you) to confirm linking.
Optionally retrieve the user's page-scoped ID (PSID) using the account linking endpoint. This step should only be used in special cases when you need the user's PSID as part of the linking process.
These steps are very easy to follow, except there's no help whatsoever on how to actually link the account, I get the redirect_uri and the account_linking_token as parameters on my callback website where I enter the account login and password.
And then, I link the accounts...? How exactly?
What's the use on this button? I know it is supposed to link accounts, but what do I need the account_linking_token for? I can already send in a regular web_url button the user psid, I can easily send it on my login button as a parameter and link account to this psid if credentials are correct.
I strongly believe there's something I'm missing or something I'm not understanding, but I don't know what. I followed the steps, called the account linking endpoint to get the PSID, which I already had since it is how I send messages with my bot, but I don't really see the point on this button.
So, what am I missing? I'm so frustated.

Just been through a similar bit of head scratching, so will explain what I've done while it's fresh in my head
For my example, I wanted Facebook to redirect out to my main login page, which is an open id connect implementation. The customer signs in to this, and I get an id_token and access_token back from that. Upon receiving the access_token, I'm extracting the 'sub' claim from the JWT, which is the unique customer identifier in our database.
I'm then redirecting back to the value that was sent to me in redirect_uri, appending authorization_code={the-value-of-the-sub-claim}
This then triggers the 'account link' webhook, which will Post to my service code, containing the PSID of the Facebook user and the authorization_code, which is my unique customer id in my business database.
You now have the 2 bits of information you need, the unique facebook id and your unique customer id in the Post message. It's up to your business code to persist this information to some sort of storage at this point
On subsequent message posts to the Bot endpoint, you always have the sender (PSID) in the message. Your code can now look up the corresponding id specific to your business and perform operations relevant for that id.
Where the linking takes place - that's in your code, you need to handle the message from the account link webhook and store the data for future use.

Related

How to make JWT token based link as one time use link for Reset Password and Email Verification functionality

1. What I have done till now
I added reset password functionality in my project in which user gets the link in their respective email. I used user's hashed password as its secret key to make the link ONE TIME USE. So if the user change his password once than the hash changes and also the secret key making the token verification invalid which in turns makes the the link ONE TIME USE. As I used user's hashed password as its secret key I also have to pass user's _id with the token in the link so that at the time of verifying the token first I fetch the user's password hash with the help of the user's _id that I passed with the token in the link.
2. What I want to do
Now it's time to add email verification functionality to my project and I am not getting any idea of how to make the verification link as one time link. And what if the users request multiple times for the email verification and I generate that many link and send it to the user's respective email.
3. I thought of doing this
I thought of creating a database for email verification and insert the user_Id and token to that database each time the user requests for the verification and once the user click any of the requested links I make the user verified and delete all the token associated to the user's user_Id so that when the user clicks any of the link or the same link again the email is already verified and token is deleted so I can response "Invalid Link or Request" to the user.
If the no. 3 is a legit mechanism I will implement same to no. 1
If the above mechanism is legit and good to go I would like to implement the same for my password reset functionality so that I no need to use user's password hash as the secret key and also not pass the user's _id in the link
Please also give suggestions if these both functionality can be done in a different way

How to authorise user for a web page in FB messenger, without logging in?

I am building a chat bot in FB messenger that saves user profile data, food and calorie consumption. I am using Node/Express/MongoDB for the backend and want the user to be able to open a personal dashboard page inside the chat with a link. So that URL would be something like www.myapp.com/:id where :id is a personal key.
The problem I have is how can only the user belonging to this page and data open this without having to login? Normally you would go to a website, login and be able to see the page, but this not a step I want in a chat bot. I want the user just to open the page in the chat, whether that is results in opening a browser tab or a native webview. Any advice on how I can achieve this?
To verify if the user on the page is the facebook user you intend the page to be for, add FB Messenger Extensions to the page.
When clicking a webview in your bot, Messenger extensions will be able to tell who they are logged in as, and allow you to do whatever you want with that info. In your case, checking if the userid matches the one passed by your bot in the url. There are many ways to check this, like splitting query strings, but I stuck with the example route in your question.
Use the following on your dashboard page. The below will check with FB who the logged in user is, and if it doesn't match the ID of the link they followed, deny them access with a redirect.
<script>
MessengerExtensions.getContext(<YOUR-APP-ID>,
function success(thread_context){
// User ID was successfully obtained.
var psid = thread_context.psid;
// Grab the user id from your url (assumes your url is /<USER_ID>)
var loc = window.location.pathname.replace(/^\/|\/$/g, '');
if (psid !=== loc) {
window.location.replace("http://YOUR_DOMAIN.com/error")
}
}, function error(err, errorMessage) {
// Error handling code
});
</script>
Docs on getting user id with Messenger Extensions
Try this:
Open Messenger, then open DevsConsole and go to Network tab. Now paste your link and click it. In the Network tab open the request details issued by the click. Under "Form Data" you should see this:
q:[{"user":<your_fb_id>,...
You can use this id to authenticate the user in your app - just couple it somehow with the authorized user in your app. This is just the first idea off the top of my head, it should be quite safe if you mix it e.g. with CORS security headers.

Using mod_scorm_insert_scorm_tracks

I'm interfacing my App with Moodle and I'm successfully calling mod_scorm_get_scorm_sco_tracks and mod_scorm_get_scorm_attempt_count via Ajax (XMLHttpRequest) for a given user (userid).
Now I want my App to push some SCORM tracks back to Moodle.
So I'm trying to use mod_scorm_insert_scorm_tracks but with no success.
The problem is that this method does not take an userid parameter, so I don't understand how to use it (and if I try to add userid to input params I get an invalid parameter exception).
I had kind of success (no error message) by sending this:
scoid=206&attempt=2&tracks[0][element]=cmi.completion_status&tracks[0][value]=completed&tracks[1][element]=cmi.interactions.0.id&tracks[1][value]=multiplechoice_page_1_1&tracks[2][element]=cmi.interactions.0.learner_response&tracks[2][value]=White&tracks[3][element]=cmi.interactions.0.result&tracks[3][value]=correct&tracks[4][element]=cmi.interactions.0.description&tracks[4][value]=Which%20color%20was%20Garibaldi's%20white%20horse%3F&tracks[5][element]=cmi.interactions.1.id&tracks[5][value]=hotobject_page_2_1&tracks[6][element]=cmi.interactions.1.learner_response&tracks[6][value]=butterfly&tracks[7][element]=cmi.interactions.1.result&tracks[7][value]=incorrect&tracks[8][element]=cmi.interactions.1.description&tracks[8][value]=Where%20is%20the%20fish%3F&tracks[9][element]=cmi.score.max&tracks[9][value]=2&tracks[10][element]=cmi.score.raw&tracks[10][value]=1&tracks[11][element]=cmi.score.scaled&tracks[11][value]=0.5&tracks[12][element]=cmi.session_time&tracks[12][value]=PT0H0M15S&tracks[13][element]=timemodified&tracks[13][value]=1480947821&tracks[14][element]=userid&tracks[14][value]=26&tracks[15][element]=scoid&tracks[15][value]=206&wstoken=69f2471506c4c49ff47cd0de0c4c9f01&wsfunction=mod_scorm_insert_scorm_tracks&moodlewsrestformat=json
However, since I cannot specify the user those data belongs to, my user's attempts does not update (as predictable).
This is the response from Moodle:
{"trackids":[44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59],"warnings":[]}
I've tried inserting the userid info into traks (tracks[14][element]=userid&tracks[14][value]=26) but still no luck.
So, the questions are:
Which user are those tracks inserted to considering that I'm calling it from an external app, so there's no logged in user in Moodle?
How can I specify that those tracks are for a give userid?
the user identity comes from the HTTP Context of a full login into Moodle: you can't provide SCORM tracking info on behalf of any user but the actual logged-in user.
More at:
https://github.com/moodle/moodle/blob/d33c67bc4744f901bf389607cfbbb683ef1c7d80/mod/scorm/classes/external.php#L451
https://github.com/moodle/moodle/blob/0b8e0c374f89ca20e5b9e7c9370761810811edc6/lib/externallib.php#L481
HTH,
Matteo

What's the best way to provide forgotten password functionality with CouchDB and Backbone.js?

I've got an ajax app built using backbone.js and it's hooked up to a couchdb instance. I am trying to build forgotten password functionality using the following workflow:
1) user enters their username
2) I send them an email with a link in it
3) the user accesses the link and enters a new password
I can't figure out how to actually get the password updated however. For security reasons, I'm not going to embed admin creds into the client, and it looks to me like a user has to be authenticated before they can make changes to their password.
Thank you for your time and assistance. Hopefully I'm just overlooking something silly.
I do it like this: save a unique key to DB, send a link that includes that key to visitor email and of course when he will access the link you will need to check the availability of that key, maybe consider 15 minutes since key was sent or decline his reset request

make turn on/off or deauthorized user from my app, and list action of user from app

I submitting an app to Facebook with open graph news read type by javascript.
All done so well with flow from user asking for authorized my app, and show the button help user can public the article then they can remove if they want to.
Today I got the request from Facebook need to change my app:
requirements
(https://developers.facebook.com/docs/opengraph/actions/builtin/#read).
Please make sure your users can (1) Turn sharing on/off globally on
each page an article appears. (2) Remove articles they shared within
your app on each page an article appears. (3) Only generate read
actions when you're sure someone is interested in reading the article
- only publish after 10 seconds.
The third request is easy just use timeout to show the button submit after user read article.
The seconds is so hard because I don't know how to full the array list of pass action of user doing with my app include action id and title of article they post which I can use to create "remove link" for each of them if user want to.
The fist request I did search for method of javascript to de-authorized the app from user (not revoke permission) so I can ask user to be reauthorized if they need.
Please help.
Beside I see very nice 2 sample in guild page
https://developers.facebook.com/attachment/OG_App_PublishToggle.png
https://developers.facebook.com/attachment/OG_App_DeleteActivity.png
But they din't give out the link of live site using it.
or may be that is one of Facebook markup similar "recommend box" , but how/where we can get it?
Please advices for the script or sample as Facebook dose will be help full
regards
UPDATE 1 I found the way to reauthorized all app or revoke one permission.
here the function:
var permsNeededPub = "publish_stream";
///notice that if permission is "publish_actions" revoke function not work
function xlfb_revokePerm() {
FB.api("/me/permissions", "delete",{permission:permsNeededPub}, function(response){
console.log(response);
if(response){
console.log(' Remove success '+permsNeededPub);
}
});
}
function xlfb_removeApp() {
FB.api("/me/permissions", "delete", function(response){
console.log("User removed the app from acount: "+response);
});
};
The seconds is so hard because I don't know how to full the array list of pass action of user doing with my app include action id and title of article they post which I can use to create "remove link" for each of them if user want to.
Whenever a user takes an OG action on your site - save the action_instance_id you are getting back from the API call and whatever extra data you might need to your database.
The fist request I did search for method of javascript to de-authorized the app from user (not revoke permission) so I can ask user to be reauthorized if they need.
Why would you want to de-authorize the app?
All that’s required here is to have a global on/off switch for all sharing activity – so if the user sets it to off, then you just don’t publish any actions for him as long as he leaves this setting set to off.

Categories