How to get Facebook test user email and password after create? - facebook

I am using Selenium to test a Facebook auth app. Currently I am using a script in the test suite to create Facebook test users by posting to the test user api found here:
https://developers.facebook.com/docs/test_users/
https://graph.facebook.com/APP_ID/accounts/test-users?
installed=true
&name=FULL_NAME
&locale=en_US
&permissions=read_stream
&method=post
&access_token=APP_ACCESS_TOKEN
This gives me back a response of:
{
"id": "1234...",
"access_token":"1234567..." ,
"login_url":"https://www.facebook.com/platform/test_account..."
"email": "example...#tfbnw.net",
"password": "1234..."
}
This gives me the username and password of the test. However If I want to reuse the user in a later test I don't know how to get this info. I might be over looking something. If I do a GET request to get a list of registered test users the response looks like this:
{
"data" [
{
"id": "1231....",
"access_token":"1223134..." ,
"login_url":"https://www.facebook.com/platform/test_account.."
}
{
"id": "1231....",
"access_token":"1223134..." ,
"login_url":"https://www.facebook.com/platform/test_account.."
}
]
}
This response dosen't give me any emails/passwords which I'd need to login the test users in a full test. I'd rather not log them in by using the access_token and login_url because this isn't true to the Facebook auth flow on the site.

See https://developers.facebook.com/docs/test_users/#changepw
Facebook does not store cleartext passwords and will only return the password on user creation per the documentation. You can change the user's password to anything at any time without knowing their password so you could set all your test users to have whatever password you want after creation and just rely on that when running your tests.

Related

Create User / Batch Create Users in Asgardeo User Management API with Auto Generated Password

Just want to ask how we can create a user using Asgardeo User Management API without providing a password?
Basically we want to replicate this flow but instead of manually doing it on the console, we want to do it from the User Management API.
enter image description here
Here are some of the Endpoints that we tested
POST
https://api.asgardeo.io/t/asgardeo/scim2
/Users
POST
https://api.asgardeo.io/t/asgardeo/scim2
/Bulk
The password field seems to be a required field.
Setting the urn:scim:wso2:schema with "askPassword":"true" should allow you to create the users without providing the password.
Sample Payload of the scim https://api.asgardeo.io/t/tenantName/scim2/Users:
{
"emails":
[
{
"primary":true,
"value":"<User Email>"
}
],
"name":
{
"familyName":"",
"givenName":""
},
"urn:scim:wso2:schema":
{
"askPassword":"true"
},
"userName":
"DEFAULT/<User Email>"
}
The will receive the invite request similar to the UI function.
Same approach can be taken with the Bulk endpoint too as mentioned this medium blog

Matching a page-scoped ID and a chatbot-scoped ID: several questions

I have a web site (gigsnet) with a Facebook login. I did it using Passport/oauth.
I want to implement a chatbot, so that our users can chat to the "Gigsnet" page, and get personalised responses from the chatbot.
I realise that the IDs won't match, and that some "magic" is necessary here. So, here we go.
SOME IDS
This is what my server receives when a message by myself (page admin) arrives:
Requested: /app/chatbot
REQUEST BODY: { object: 'page',
entry:
[ { id: '1130858117040228',
time: 1495584613258,
messaging:
[ { sender: { id: '119XXXXXX7137093' },
recipient: { id: '1130858117040228' },
timestamp: 1495584613013,
message:
{ mid: 'mid.$cAAQEgkm16DpiaQ9qlVcN8ohagocY',
seq: 290123,
text: 'd' } } ] } ] }
POST /app/chatbot 200 1.581 ms - -
This tells me that my user ID for the chatbot is 119XXXXXX7137093.
Also, this is what I have on my DB for authenticated users:
{ "_id" : ObjectId("5924c947b0d5a1095c8f326c"), "strategyId" : "facebook", "field1" : "636379230", "field3" : "EAAGcvqGZBOtkBAFuHIC4U9CxB8vEFcL25iQ6vsVkT9s1CKfJtqPPg6YhJjZAepu2v6EqtOjj6UDCaTYxca9UbRReIhKeIu4UGmEW4L9lJcGDXXXXXXXXXXXXXXXl4YgoMx8ExmI0zZCEsbZBYtZA9SR3PW9FkMdZCkgZD", "userId" : ObjectId("59239720a04b2e1de8e103d8"), "id" : ObjectId("5924c947b0d5a1095c8f326b"), "_children" : { }, "_clean" : true }
This particular user happens to be admin of the pages, the app, and owner of the company that owns page and app.
So:
USER ID (CHATBOT SCOPE): 119XXXXXX7137093
USER ID (LOGIN APP SCOPE): 636379230 WITH ADMIN ACCESS TOKEN: EAAGcvqGZBOtkBAFuHIC4U9CxB8vEFcL25iQ6vsVkT9s1CKfJtqPPg6YhJjZAepu2v6EqtOjj6UDCaTYxca9UbRReIhKeIu4UGmEW4L9lJcGDXXXXXXXXXXXXXXXl4YgoMx8ExmI0zZCEsbZBYtZA9SR3PW9FkMdZCkgZD
PAGE ID: gigsnetco
APP ID (LOGIN APP): 453817548028633
The access token is important as I am the admin for the pages.
USER ID IN MESSENGER BOT -> USER ID IN LOGIN APP (with extra step)
To make this call, I need FIRST an access token for the page. So, here I am using my user's oauth access token from the database in order to get another access token, the one to administer pages.
curl "https://graph.facebook.com/v2.9/gigsnetco?access_token=EAAGcvqGZBOtkBAFuHIC4U9CxB8vEFcL25iQ6vsVkT9s1CKfJtqPPg6YhJjZAepu2v6EqtOjj6UDCaTYxca9UbRReIhKeIu4UGmEW4L9lJcGDXXXXXXXXXXXXXXXl4YgoMx8ExmI0zZCEsbZBYtZA9SR3PW9FkMdZCkgZD&fields=access_token"
{"access_token":"EAAGcvqGZBOtkBAMeNZAE09EsRndMYvDlVpNeE6HT05zxqeL2XXXXXXXXXXXXXXXXDs2vdiSYlErrdw8ZAF3uBdUiIjnioXxohljA3mLjlKbgFZC5tfz7ivGHCHb4LubXHBNx7wLMMLcl7WrZC627uca2HW18dQZBH5MGhOqvHRyYXQZDZD","id":"1130858117040228"}
I now use the token for the page ID above to make a request on the user 119XXXXXX7137093 (chatbot) asking it the list of ids for linked pages.
Note: I am using the user id 119XXXXXX7137093, filtering by app ID, using the page's access token.
curl "https://graph.facebook.com/v2.9/119XXXXXX7137093/ids_for_apps?app=453817548028633&access_token=EAAGcvqGZBOtkBAMeNZAE09EsRndMYvDlVpNeE6HT05zxqeL2XXXXXXXXXXXXXXXXDs2vdiSYlErrdw8ZAF3uBdUiIjnioXxohljA3mLjlKbgFZC5tfz7ivGHCHb4LubXHBNx7wLMMLcl7WrZC627uca2HW18dQZBH5MGhOqvHRyYXQZDZD"
{"data":[{"id":"636379230","app":{"link":"http:\/\/www.gigsnet.com\/","name":"Login","id":"453817548028633"}}],"paging":{"cursors":{"before":"NDUzODE3NTQ4MDI4NjMz","after":"NDUzODE3NTQ4MDI4NjMz"}}}
Bingo! I have 636379230. When a user types anything to the chatbot, I can now cross-reference them with a user who has previously logged in, and provide personalised information.
USER ID IN LOGIN ALL -> USER ID IN MESSENGER
Here I am using the access token from the screen https://developers.facebook.com/apps/453817548028633/messenger/ in "Token generation".
curl "https://graph.facebook.com/v2.9/636379230/ids_for_apps?app=453817548028633&access_token=EAAGcvqGZBOtkBAKycZAeDI4D13sOVZAZAlNJqZCTXXXXXXXXXXXXXXXxsyaOs9WgQO2jcnHJeEYAbUlEdCU1xejYjTlWE1w4tEfe7IZAAw8i3X2qn1AKwDlHhwHbQsoylxPZAcPagVKemSd6KQwUP2gB8pkm61PumqLiVuIw3B3lQZDZD"
{"data":[{"id":"636379230","app":{"link":"http:\/\/www.gigsnet.com\/","name":"Login","id":"453817548028633"}}],"paging":{"cursors":{"before":"NDUzODE3NTQ4MDI4NjMz","after":"NDUzODE3NTQ4MDI4NjMz"}}}
Note that my own access token (I guess because I am the page admin) ALSO works:
curl "https://graph.facebook.com/v2.9/636379230/ids_for_apps?app=453817548028633&access_token=EAAGcvqGZBOtkBAFuHIC4U9CxB8vEFcL25iQ6vsVkT9s1CKfJtqPPg6YhJjZAepu2v6EqtOjj6UDCaTYxca9UbRReIhKeIu4UGmEW4L9lJcGDXXXXXXXXXXXXXXXl4YgoMx8ExmI0zZCEsbZBYtZA9SR3PW9FkMdZCkgZD"
{"data":[{"id":"636379230","app":{"link":"http:\/\/www.gigsnet.com\/","name":"Login","id":"453817548028633"}}],"paging":{"cursors":{"before":"NDUzODE3NTQ4MDI4NjMz","after":"NDUzODE3NTQ4MDI4NjMz"}}}
Bingo! 636379230 is the user ID for messenger.
QUESTIONS
The API documentation mentions that I should provide appsecret_proof in order to get ids_for_pages to work. However, I didn't have to (plus, you only provide a PHP example, and I couldn't find an example in node). Is it OK not to provide appsecret_proof?
In order to make calls, I am using my own access token (as the page admin); I obtained this access token using oauth, using my app (I am using passport on nodejs).
Will this token expire after 60 days?
If so, does that mean that I ought to link/unlink my account so that I generate a new access token? (Or, use an API command to get a new access token? (If so, which one?)
Since the access token expires, shall I keep on refreshing it for logged in users as well? The problem is that once a user is logged in, they are alogged in.
Does the page access token also expire? How often shall I re-generate it? Surely, regenerate it for every received message would be wasteful on my end and your end...!
Are scoped IDs stable? Do I absolutely know that the IDs will never change? Once I make the connection, can I save it and have it like that forever? Even if a user unlinks themselves with oauth and then link themselves back? Or in case the access tokens expire for example. If they do change, how do I know if they are expired/?
Thank you!

Google Sign-In with Passportjs not getting authenticated

I'm using Sails with Passport for authentication. I'm using passport-google-oauth(OAuth2Strategy) and passport-facebook for enabling Google Sign-in.
I'm not too well-versed with Passport, so pardon me if this is a rookie question. I've set up login via Facebook and it works just fine. With Google, I do receive an authorization code after allowing access to the app, but the I'm eventually not authenticated. I'm guessing the same code should work for both Facebook and Google since the strategies are both based on oauth2.
I'm not even sure what code to share, since I'm using the auto-generated code from sails-generate-auth, but do let me know if there's anything else I can share.
Any ideas on why this might be happening? The app is locally hosted but that's unlikely to be the problem since I am getting to the authorization stage anyway.
I faced the same problem and it was located here in in api/services/passport.js:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
The Google service was not returning a profile.username property.
Because of it, the user is not saved in the database and cannot be authenticated. Then the passport callback receives an empty user, so the function that handles errors is fired and the user is redirected to the login page.
This change allows to use the displayName property as the username:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
/** Content not generated BEGIN */
// If the username property was empty and the profile object
// contains a property "displayName", add it to the user.
if (!user.username && profile.hasOwnProperty('displayName')) {
console.log(profile); // <= Use it to check the content given by Google about the user
user.username = profile.displayName;
}
/** Content not generated END */
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
You could also use the profile.id property because profile.displayName is not necessarily unique (ie: two Google accounts can have an identical displayName). But it is also true accross different services: a Twitter account could also have the same username than a Facebook account. If both register on your application, you will have a bug. This is a problem from the code generated by sails-generate-auth and you should adapt it with the behavior that you want.
I will propose a PR if this solution works for you too.
Alright, so this ultimately turned out to be a known issue with the API.
TL;DR: Enable the Google+ API and the Contacts API as mentioned here. (The Contacts API isn't required, as #AlexisN-o pointed out in the comments. My setup worked as desired with Contacts API disabled. This obviously depends on what scope you're using.)
I believe it's not a nice way of failing since this was an API error that was prevented from bubbling up. Anyway, I dug into passport.authenticate to figure out what was going wrong. This eventually calls the authenticate method defined in the package corresponding to the strategy (oauth2 in this case). In here (passport-google-oauth/lib/passport-google-oauth/oauth2.js) I found that the accessToken was indeed being fetched from Google, so things should be working. This indicated that there was a problem with the requests being made to the token urls. So I ventured a little further into passport-oauth2/lib/strategy.js and finally managed to log this error:
{ [InternalOAuthError: failed to fetch user profile]
name: 'InternalOAuthError',
message: 'failed to fetch user profile',
oauthError:
{ statusCode: 403,
data: '{
"error": {
"errors": [{
"domain": "usageLimits",
"reason": "accessNotConfigured",
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration.",
"extendedHelp": "https://console.developers.google.com"
}],
"code": 403,
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration."
}
}'
} }
This was the end of the hunt for me and the first result for the error search led to the correct answer. Weird fix though.

Can't login via Facebook iOS SDK 3 with a test user

Have a code that is working with ordinary FB user (login and post). Just created test user but unable to login. Getting message "we didn't recognize your email address or phone number". After calling https://graph.facebook.com/362652477144946/accounts/test-users?... I got:
{
"id": "100004233554579",
"access_token": "...",
"login_url": "https://www.facebook.com/platform/test_account_login.php?user_id=100004233554579&n=Ffaa4FVusNloYGS",
"email": "iosproject_gaxfjez_iosproject\u0040tfbnw.net",
"password": "..."
}
Tried entering "100004233554579", "Ffaa4FVusNloYGS" and "iosproject_gaxfjez_iosproject\u0040tfbnw.net" at username but nothing works. Any ideas?
UPDATE1 Noticed "\u0040" in email, so changed that to "#". But then getting "We didn't recognize your email" :)
UPDATE2 Noticed there's another email "100004233554579#facebook.com" when logged to Facebook login_url but it doesn't work too.
I faced the same problem with test facebook user login from mobile device - "we didn't recognize your email address or phone number".
What I did:
Went to dev console and created new test user
Clicked edit and changed password in console - than was a mistake
After you change password via dev console - facebook also changes test email. And you are able to login only at facebook.com website (not android, iOs or m.facebook.com) - because you get a security warning that email was changed. Also you can't use simple emails like qwerty.
What you need to do to get it work:
Create new test user in console (do not change anything)
Go to Graph API, generate application token, get test users via {app_id}/accounts/test-users (details)
POST new password (only password) to the test user /{user_id} (details)
Now you shall be able to login using m.facebook.com, Android or iOS apps
A little bit wierd
From your response, it seems like the email required for login should be
iosproject_gaxfjez_iosproject#tfbnw.net.
That should work for you with the password generated.
You can read more about creating test users here.
If it still doesn't solve your issue, please create a bug report at
http://developers.facebook.com/bugs and we'll be more than happy to look into it.

Facebook access token server-side validation for iPhone app

I'm developing iPhone application, that is based on communication with server, and I want to use Facebook authentication mechanisms.
Basically, I think it should work like this:
In my iPhone app, user logs in to Facebook, using his email and password.
User allows access to his data for related Facebook application.
My iPhone app receives access token, after successful log in.
In further communication with my server, my iPhone application should use the received Facebook access token (for example: in queries).
When my server receives some query from iPhone app, with access token, it should ask Facebook that this token is valid (and for who), and if yes, server should assume that user is authenticated with Facebook.
My question is: how the server should ask Facebook if given access token is valid? I think I should somehow check if the token is valid for my Facebook app.
I've tried many Facebook queries to graph API, that I've found, but nothing worked as I expected. Can you provide me some example?
Here's a two step process you can use to validate that a user access token belongs to your App:
1) Generate an App Access token
(https://developers.facebook.com/docs/howtos/login/login-as-app/)
https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID
&client_secret=YOUR_APP_SECRET
&grant_type=client_credentials
2) Debug the User Access token
(https://developers.facebook.com/docs/howtos/login/debugging-access-tokens/)
https://graph.facebook.com/debug_token?
input_token=INPUT_TOKEN
&access_token=ACCESS_TOKEN
Where INPUT_TOKEN is the user access token you want to verify, and ACCESS_TOKEN is your app's token that you got from step 1.
The debug endpoint basically dumps all information about a token, so it'll respond with something like this:
{
data: {
app_id: YOUR_APP_ID,
is_valid: true,
metadata: {
sso: "iphone-safari"
},
application: YOUR_APP_NAMESPACE,
user_id: USER_ID,
issued_at: 1366236791,
expires_at: 1371420791,
scopes: [ ]
}
}
If that token isn't from "your app" then it will return an error response.
Update: this answer seems insecure since it doesn't validate the token
first as belonging to your app, see the comments, original answer as
follows:
I assume that you already have the access token in hand. In such a case the simplest way to validate an access token is to issue the following request
https://graph.facebook.com/me?fields=id&access_token=#accesstoken
Here replace #accesstoken with the access token you have. I will breakdown the url and will explain each.
We are issuing a graph api request here which will return the Facebook User Id of the owner of the access token as a JSON string. The keyword 'me' represents the currently logged in user or the owner of the access token. For this request access token is a mandatory parameter.
If the provided access token is not valid or expired Facebook will just return an error message of some sort.
For a valid access token the result will somehow look like this
{
"id": "ID_VALUE"
}
Another solution would be to use https://graph.facebook.com/app/?access_token=[user_access_token] as described by Get application id from user access token (or verify the source application for a token).
This appears to be an undocumented feature, but returns JSON containing the id of the app the token was generated for. If the token wasn't for your app, it returns a 400.
In the latest version of facebook (2.2) you can do it this way:
https://developers.facebook.com/docs/graph-api/reference/v2.2/debug_token
Sample output:
{
"data": {
"app_id": "THE APP ID",
"application": "APP NAME",
"expires_at": 1427245200,
"is_valid": true,
"scopes": [
"public_profile",
"basic_info",
"read_stream",
"email",
"publish_actions",
"read_friendlists",
"user_birthday",
"user_hometown",
"user_location",
"user_likes",
"user_photos",
"user_videos",
"user_friends",
"user_posts"
],
"user_id": "THE USER ID"
}
}
private function facebookRequestMe($access_token)
{
include_once "facebook.php";
$facebook = new Facebook(array(
"appId" => "your_application_id",
"secret" => "your_application_secret"
));
$facebook->setAccessToken($access_token);
return $facebook->api("/me", "GET");
}
You can download the Facebook SDK for PHP from GitHub.
If a user has passed you a Facebook UID that they claim is theirs and you want to check if it's legit, this is a Python function that will verify it against their access token (an implementation of Robin Jome's answer):
def verify_facebook_id(id, access_token):
import requests
import simplejson
params = {'fields': 'id', 'access_token': access_token}
text = requests.get("https://graph.facebook.com/me", params=params).text
json = simplejson.loads(text)
response_id = json["id"]
return response_id == id
This is the only secure method to verify user token using just one request:
https://graph.facebook.com/debug_token?input_token={token-to-inspect}&access_token={app_id}|{app_secret}
Note that a sign "|" in the above URL isn't used as OR but as separator and must be there after fill the other fields.
The response will be JSON looking like that:
{
data: {
app_id: {app_id},
application: {app_name},
expires_at: {some_number},
is_valid: {true|false}
scopes: {array_of_permissions},
user_id: {user_id}
}
}
Reference: https://developers.facebook.com/docs/facebook-login/access-tokens/#apptokens
(above method is mentioned at the bottom of this section)
Along with an access token Facebook also sends an "expires_in" parameter, which is an offset value. Use that to compute for when the access token will expire as an NSDate. Then when you need to do a request compare the current date with the expiration date.
Also try to inspect the status codes and response strings Facebook sends back.