I am trying to get user's email using FB.API() method, all code is below
public class FacebookCase : MonoBehaviour {
// Use this for initialization
void Start () {
FB.Init(new Facebook.InitDelegate(initComplete), null, null);
}
private void initComplete()
{
FB.Login("email,publish_actions", new Facebook.FacebookDelegate(loginComplete));
}
private void loginComplete(FBResult result)
{
FB.API("/me?fields=first_name,last_name,email", Facebook.HttpMethod.GET, graphCallback);
}
private void graphCallback(FBResult result)
{
Debug.Log(result.Text);
}
}
That code gives me first and last name, but instead of email address I've got 'id=2385905023865'.
Why it so? How to get email?
The id field is always returned. It's not shown "instead" of the email field. My suspicion is that you didn't request the email permission properly during login. Please check accordingly...
Related
I am testing example-crud for applying your framework in my project. But I noticed some bug.
I try to get value from the sent json into std::string with this way:
std::string test = userDto->userName->c_str();
ENDPOINT("POST", "users", createUser, BODY_DTO(Object<UserDto>, userDto))
{
std::string test = userDto->userName->c_str();
return createDtoResponse(Status::CODE_200, m_userService.createUser(userDto));
}
UserDto defined like this:
class UserDto : public oatpp::DTO {
DTO_INIT(UserDto, DTO)
DTO_FIELD(Int32, id);
DTO_FIELD(String, userName, "username");
};
If i send correct json with post query, i get value to "test" variable properly.
{
"id": 0,
"username": "test_user"
}
But if i change json`s field "username" to, as example, "Username" and send this json to endpoin, server will faild with error "Segmentation fault".
Server must'n faild under such condition. It must giv error message to the sender, and continue run.
How can i avoid the failure, if i just neen to get one simple value to variable?
Since the DTO field name and the JSON-key doesn't match, the userName of the received DTO is null. So the solution would be to add a nullptr check:
ENDPOINT("POST", "users", createUser,
BODY_DTO(Object<UserDto>, userDto))
{
OATPP_ASSERT_HTTP(userDto->userName, Status::CODE_400, "username is required!"); // check field for nullptr
std::string test = userDto->userName->std_str();
...
return createDtoResponse(Status::CODE_200, m_userService.createUser(userDto));
}
Source: https://github.com/oatpp/oatpp/issues/340#issuecomment-727563144
Someone is logged into my app. I need to display some profiles of people that might not be on this person's friends list. Is that possible, or is it a privacy issue. A person's "public profile" should be accessible right?
I tried to get the first name, profile picture and gender
Bundle parameters = new Bundle();
parameters.putString("fields", "first_name,gender");
try {
new GraphRequest(
AccessToken.getCurrentAccessToken(),
"/" + user.getUserID(),
parameters,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
JSONObject facebookResponse = response.getJSONObject();
try {
final String first_name = facebookResponse.getString("first_name");
final String gender = facebookResponse.getString("gender");
Bundle params = new Bundle();
params.putBoolean("redirect", false);
params.putString("type", "square");
params.putInt("width", 200);
params.putInt("height", 200);
new GraphRequest(
AccessToken.getCurrentAccessToken(),
"/" + user.getUserID() + "/picture",
params,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
JSONObject facebookResponse = response.getJSONObject();
try {
JSONObject data = facebookResponse.getJSONObject("data");
String url = data.getString("url");
Name.setText(first_name);
Gender.setText(gender);
mNetworkImageView.setImageUrl(url, mImageLoader);
facebookResponseListener.updatedUserObject(first_name, url, gender, pos);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
).executeAsync();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
).executeAsync();
} catch (Exception uee) {
uee.printStackTrace();
}
all of this is inside the getView() if a listview (it's where I display the profiles). While testing, I'm getting all the information of the friends of the logged in person, but the "gender" property in the response object is missing from the non-friend. Only the name and userID is being returned.
It's all explained in the docs (https://developers.facebook.com/docs/facebook-login/permissions):
gender & locale can only be accessed if:
The person queried is the person using the app.
The person queried is using the app, and is a friend of the person
using the app.
The person queried is using the app, is not a friend of the person
using the app, but the app includes either an app access token or an
appsecret_proof argument with the call.
I am using facebook SDK 4.0.1. I gave permission for user_friends but I am not able to get friend list of the user. I am getting the count of the user's friends but I want the name of the user's friends and ids
private FacebookCallback<LoginResult> mcallback = new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
accessToken = loginResult.getAccessToken();
Log.d("Access Token", accessToken.toString());
Profile profile = Profile.getCurrentProfile();
// Log.d("PROFILE","PROFILE IMAHE"+profile.getName());
displayWelcomeMessage(profile);
GraphRequestBatch batch = new GraphRequestBatch(
GraphRequest.newMeRequest(accessToken, new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject jsonObject, GraphResponse response) {
try {
SharedPreferences.Editor editor = prefs.edit();
editor.putString(Constant.KEY_ID,jsonObject.getString("id"));
editor.putString(Constant.KEY_USER_NAME,jsonObject.getString("name"));
editor.putString(Constant.KEY_USER_FNAME,jsonObject.getString("first_name"));
editor.putString(Constant.KEY_USER_LNAME,jsonObject.getString("last_name"));
// hometown = jsonObject.getJSONObject("hometown");
// editor.putString(Constant.KEY_USER_HOMETOWN,hometown.getString("name"));
editor.putString(Constant.KEY_USER_EMAIL,jsonObject.getString("email"));
editor.putString(Constant.KEY_USER_GENDER,jsonObject.getString("gender"));
// editor.putString(Constant.KEY_USER_DOB,jsonObject.getString("birthday"));
editor.commit();
// town = hometown.getString("name");
// personId = jsonObject.getString("id");
// gen = jsonObject.getString("gender");
// email = jsonObject.getString("email");
Log.d("RESPONCE", "RESPONCE user=" + jsonObject.toString());
Log.d("RESPONCE", "RESPONCE =" + response.toString());
}
catch (JSONException e) {
e.printStackTrace();
}
}
}),
GraphRequest.newMyFriendsRequest(accessToken, new GraphRequest.GraphJSONArrayCallback() {
#Override
public void onCompleted(JSONArray jsonArray, GraphResponse response) {
//Lo Application code for users friends
Log.d("RESPONCE FRIEND", "RESPONCE FRIEND=" + jsonArray.toString());
Log.d("RESPONCE FRIEND", "RESPONCE =" + response.toString());
response.getJSONArray();
}
}));
batch.addCallback(new GraphRequestBatch.Callback() {
#Override
public void onBatchCompleted(GraphRequestBatch graphRequests) {
// Application code for when the batch finishes
}
});
batch.executeAsync();
Since v2.0 of the Graph API, it is only possible to get friends who authorized your App too - for privacy reasons. More information can be found in this and many other threads about that exact same question: Facebook Graph Api v2.0+ - /me/friends returns empty, or only friends who also use my app
(Using ASP.NET Identity 2.1, Microsoft.Owin.Security.Facebook 3.0.1 in a Web API project)
From here: https://developers.facebook.com/docs/facebook-login/login-flow-for-web/v2.2
This is because once someone has declined a permission, the Login Dialog will not re-ask them for it unless you explicitly tell the dialog you're re-asking for a declined permission.
You do this by adding the auth_type: rerequest flag to your FB.login() call:
FB.login(
function(response) {
console.log(response);
},
{
scope: 'user_likes',
auth_type: 'rerequest'
}
);
When you do that, the Login Dialog will re-ask for the declined permission. The dialog will look very much like the dialog in the section on re-asking for permissions but will let you re-ask for a declined permission.
So, using ASP.NET Identity's integration with Facebook login, I know how to pass in the requested scope, but if the user declines the permission, I need to pass in the extra parameter "auth_type" : 'rerequest." How do I do that?
You first add your custom FacebookAuthenticationProvider
public class FacebookProvider : FacebookAuthenticationProvider
{
public override void ApplyRedirect(FacebookApplyRedirectContext context)
{
//To handle rerequest to give some permission
string authType = string.Empty;
if (context.Properties.Dictionary.ContainsKey("auth_type"))
{
authType = string.Format("&auth_type={0}", context.Properties.Dictionary["auth_type"]);
}
//If you have popup loggin add &display=popup
context.Response.Redirect(string.Format("{0}{1}{2}", context.RedirectUri, "&display=popup", authType));
}
}
now in the startup you need to use this provider
var options = new FacebookAuthenticationOptions
{
AppId = "appid",
AppSecret = "secret",
Provider = new FacebookProvider
{
OnAuthenticated = async context =>
{
foreach (var x in context.User)
{
if (x.Key == "birthday")
{
context.Identity.AddClaim(new Claim("dateofbirth", x.Value.ToString()));
}
else
{
context.Identity.AddClaim(new Claim(x.Key, x.Value.ToString()));
}
}
context.Identity.AddClaim(new Claim("fb_accecctoken", context.AccessToken));
await Task.FromResult(context);
}
}
};
options.Scope.Add("public_profile");
options.Scope.Add("email");
options.Scope.Add("user_birthday");
options.Scope.Add("user_location");
app.UseFacebookAuthentication(options);
and finally in your account controller you need to set auth_type when you need
private const string XsrfKey = "xsrfkey";
internal class ChallengeResult : HttpUnauthorizedResult
{
public ChallengeResult(string provider, string redirectUri)
: this(provider, redirectUri, null, false)
{
}
public ChallengeResult(string provider, string redirectUri, string userId, bool isRerequest)
{
LoginProvider = provider;
RedirectUri = redirectUri;
UserId = userId;
IsRerequest = isRerequest;
}
public string LoginProvider { get; set; }
public string RedirectUri { get; set; }
public string UserId { get; set; }
public bool IsRerequest { get; set; }
public override void ExecuteResult(ControllerContext context)
{
var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
if (IsRerequest)
{
properties.Dictionary["auth_type"] = "rerequest";
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}
I had the same issue when I wanted to ensure the user had accepted all my permissions. As you probably know this can be detected by calling the /me/permissions url.
So I eventually solved it by simply deleting my app from the user's account.
You can do so by doing a DELETE request on the /me/permissions URL as documented here.
This will remove all permissions you requested from the user, so next time you try authenticating him through Facebook, the prompt appears again.
I need to have Sitecore send an email to a particular email address whenever a user gets locked out of Sitecore by entering an incorrect password too many times. I have code to send an email; however, I don't see a pipeline that fires during the login process (loggedin and loggingin only fire upon successful login).
Had to modify #Maras's answer a little bit to get it to work as the domain is not prefixed to the UserName property in the LoggingIn Event. Other than that the code works great.
namespace My.Namespace.Login
{
public class CustomLoginPage : LoginPage
{
private bool _userIsNotLockedOut;
protected override void OnInit(EventArgs e)
{
Login.LoggingIn += Login_LoggingIn;
Login.LoginError += Login_LoginError;
base.OnInit(e);
}
private void Login_LoggingIn(object sender, LoginCancelEventArgs e)
{
string domainUser = Login.UserName;
if (!domainUser.Contains("sitecore\\"))
{
var domain = Sitecore.Context.Domain;
domainUser = domain + #"\" + domainUser;
}
var user = Membership.GetUser(domainUser, false);
if (user != null)
{
_userIsNotLockedOut = !user.IsLockedOut;
}
}
private void Login_LoginError(object sender, EventArgs e)
{
if (_userIsNotLockedOut)
{
var user = Membership.GetUser(Login.UserName, false);
if (user != null && user.IsLockedOut)
{
SendEmail();
}
}
}
}
}
Also you need to reference the Sitecore.Client.dll, testing done in Sitecore 7.
This solution assumes that you're using standard Sitecore login page.
I managed to achieve what you need with overriding Sitecore login page. What you need to do is to create a class which inherits from Sitecore.sitecore.login.LoginPage (it's not a typo) class and then add 2 methods which will be executed before logging in to the system and after login failed as follows:
namespace My.Assembly.Namespace
{
public class MyLoginPage : LoginPage
{
private bool maybeWillBeLockedOut;
protected override void OnInit(EventArgs e)
{
Login.LoggingIn += Login_LoggingIn;
Login.LoginError += Login_LoginError;
base.OnInit(e);
}
void Login_LoggingIn(object sender, LoginCancelEventArgs e)
{
MembershipUser user = Membership.Provider.GetUser(Login.UserName, false);
// user with username exists and is not locked out yet
maybeWillBeLockedOut = user != null && !user.IsLockedOut;
}
void Login_LoginError(object sender, EventArgs e)
{
if (maybeWillBeLockedOut)
{
// login failed - lets check if locked out now
MembershipUser user = Membership.Provider.GetUser(Login.UserName, false);
if (user != null && user.IsLockedOut)
{
// user wasn't locked out but is now - send an email
SendEmail();
}
}
}
}
}
Then update sitecore\login\default.aspx file and set the new class in Inherits attribute:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs"
Inherits="My.Assembly.Namespace.MyLoginPage" %>
This is not the most elegant solution but as you and #OptimizedQuery noticed, LoggingIn and LoggedIn pipelines are not sufficient in this scenario.
I added a custom pipeline process just before the Sitecore.Pipelines.LoggingIn.CheckStartPage, Sitecore.Kernel processor in the loggingin pipeline process. When I entered a valid username and invalid password, my breakpoint was hit before I was notified that my login was unsuccessful. If your custom processor comes after the CheckStartPage processor, then it would only get hit upon successful login because the CheckStartPage process aborts the pipeline if the username/password combination fails validation. I am unsure how to check for a locked out user but it appears you should be able to add your processor before the CheckStartPage processor or override that processor.
My testing and Reflecting was done on a Sitecore 6.6 solution.