Facebook SDK detect user changed in Facebook Apps itself - android

I would like to ask that is there any methods in Facebook SDK able to identify whether the user logged in in the Facebook Apps changed or not? Because I am using the AccessToken.CurrentAccessToken method to check whether user logged in before or not, but it won't update if user in Facebook Apps changed. Thanks!
Here is how I perform checking:
// Get the current access token if user logged in before
AccessToken objAccessToken = AccessToken.CurrentAccessToken;
// Check the token value, access token validity and data access validity
bool blnIsLoggedIn = objAccessToken != null && !objAccessToken.IsExpired && !objAccessToken.IsDataAccessExpired;
if (blnIsLoggedIn)
{
// If user logged in, direct perform to get user profile
GetFacebookUserProfile(objAccessToken, strUserProfileScopes);
}
else
{
// If user not logged in, perform login
LoginManager.Instance.LogIn(CurrentActivity, DefaultScopes);
}
private void GetFacebookUserProfile(AccessToken objAccessToken, string strUserProfileScopes)
{
GraphRequest objGraphRequest = GraphRequest.NewMeRequest(objAccessToken, new clsGraphJSONObjectCallback());
Bundle objParameters = new Bundle();
objParameters.PutString("fields", strUserProfileScopes);
objGraphRequest.Parameters = objParameters;
objGraphRequest.ExecuteAsync();
}

Related

Cognito User Pool: How to refresh Access Token Android

How do you refresh the access token using Cognito for Android? The documentation suggest the following (https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-android-sdk.html):
// Implement authentication handler
AuthenticationHandler handler = new AuthenticationHandler {
#Override
public void onSuccess(CognitoUserSession userSession) {
// Authentication was successful, the "userSession" will have the current valid tokens
// Time to do awesome stuff
}
#Override
public void getAuthenticationDetails(final AuthenticationContinuation continuation, final String userID) {
// User authentication details, userId and password are required to continue.
// Use the "continuation" object to pass the user authentication details
// After the user authentication details are available, wrap them in an AuthenticationDetails class
// Along with userId and password, parameters for user pools for Lambda can be passed here
// The validation parameters "validationParameters" are passed in as a Map<String, String>
AuthenticationDetails authDetails = new AuthenticationDetails(userId, password, validationParameters);
// Now allow the authentication to continue
continuation.setAuthenticationDetails(authDetails);
continuation.continueTask();
}
#Override
public void getMFACode(final MultiFactorAuthenticationContinuation continuation) {
// Multi-factor authentication is required to authenticate
// A code was sent to the user, use the code to continue with the authentication
// Find where the code was sent to
String codeSentHere = continuation.getParameter()[0];
// When the verification code is available, continue to authenticate
continuation.setMfaCode(code);
continuation.continueTask();
}
#Override
public void authenticationChallenge(final ChallengeContinuation continuation) {
// A custom challenge has to be solved to authenticate
// Set the challenge responses
// Call continueTask() method to respond to the challenge and continue with authentication.
}
#Override
public void onFailure(final Exception exception) {
// Authentication failed, probe exception for the cause
}
};
user.getSession(handler);
Here is why this does not work. The user object which I am getting the Session for is no longer authenticated when the token expires. So retrieving the cached user via the below, will return null
CognitoUser user = userPool.getCurrentUser();
Because the above returns null, I try to get the user object by id
CognitoUser user = userPool.getUser(userId);
Which works perfectly, except that user is not authenticated and will fail during the following callback stage because the userID is null
#Override
public void getAuthenticationDetails(final AuthenticationContinuation continuation, final String userID)
Only when I attempt this call before the token expires does this work, and I can receive a new access token. But how to do this after the token has expired? Any help on this would be appreciated. Thanks in advance
When you call getSession(...) - to get tokens - and if the cached tokens have expired, the SDK will automatically refresh tokens (as long as the refresh token has not expired). If the refresh token too has expired, then getAuthenticationDetails(...) is invoked because now the user credentials (username, password, etc) are required to get new set of tokens. It should not matter how you get the user object, i.e. through getCurrentUser() or getUser(...) methods, as long as there are valid cached tokens or if the tokens can be refreshed, you will get valid tokens with getSession(...).
Retry with the latest SDK (ver 2.3.1).

How can I edit a phone number of a user in user pool of `AWS cognito` before the user is authenticated?

I using AWS cognito to verify the user's phone number. I have a problem:
When the user enter his details, I send it to AWS.
AWS try to send code to the user's phone number, but if the user enter a wrong number AWS return exception "invalid phone number". So I ask the user to update the number, but when I try to update it in AWS, they return exception "the user is not authenticated". How can I update the number to the right number after the user just signup and still not confirmed?
This is my code:
// Create a CognitoUserAttributes object and add user attributes
CognitoUserAttributes userAttributes = new CognitoUserAttributes();
// Add the user attributes. Attributes are added as key-value pairs
// Adding user's given name.
// Note that the key is "given_name" which is the OIDC claim for given name
userAttributes.addAttribute("name", userName);
userAttributes.addAttribute("family_name", userFamily);
// Adding user's phone number
userAttributes.addAttribute("phone_number", prepareValidPhoneNumberForAWS(userPhone));
SignUpHandler signupCallback = new SignUpHandler()
{
int t=0;
#Override
public void onSuccess(CognitoUser cognitoUserUser, boolean userConfirmed, CognitoUserCodeDeliveryDetails cognitoUserCodeDeliveryDetails)
{
// Sign-up was successful
// Check if this user (cognitoUser) has to be confirmed
if(!userConfirmed)
{
t=0;
// This user has to be confirmed and a confirmation code was sent to the user
// cognitoUserCodeDeliveryDetails will indicate where the confirmation code was sent
// Get the confirmation code from user
}
else
{
// The user has already been confirmed
t=1;
}
}
#Override
public void onFailure(Exception exception)
{
// Sign-up failed, check exception for the cause
exception.printStackTrace();
}
};
userPool.signUpInBackground(currentUser.getUser_id(),currentUser.getUuid(),userAttributes,null,signupCallback);
Currently this usecase is not supported by Cognito because customer needs to be signed-in to update the phone number and unconfirmed accounts cannot sign-in.
One option is to let user create a new account with the correct email address. Another option is that end user contacts developer, developer can use AdminUpdateUserAttributes to update the user phone number.

Create Backendless user after successful Google login

I'm starting to use Backendless.com mBaaS on Android
I sign in user via Google and I got token and everything is OK, but the logged in user isn't created an Users table, so I can not use it to store user specific data.
So I tried to combine user login from here with user creation from documentation:
if (result.isSuccess()) {
logined = true;
loginInBackendless(result.getSignInAccount());
BackendlessUser user = new BackendlessUser();
user.setProperty("email", result.getSignInAccount().getEmail().toString());
user.setProperty("name", result.getSignInAccount().getDisplayName().toString());
user.setPassword(UUID.randomUUID().toString());
Backendless.UserService.register(user, new AsyncCallback<BackendlessUser>() {
public void handleResponse(BackendlessUser registeredUser) {
// user has been registered and now can login
}
public void handleFault(BackendlessFault fault) {
// an error has occurred, the error code can be retrieved with fault.getCode()
}
});
the question is:
Is it right way to create user? it seems not OK, because every time google user is logged in, a new Backendless user is created (or his record in Users table is updated).

get email from android facebook sdk

i have working code to get user info except the email. this is my request code:
private void requestLoginFb() {
Session session = Session.getActiveSession();
if (!session.isOpened() && !session.isClosed()) {
session.openForRead(new Session.OpenRequest(this).setPermissions(
Arrays.asList("basic_info", "email")).setCallback(
fbCallback));
} else {
Session.openActiveSession(act, true, fbCallback);
}
}
here where i get user info
Request.executeMeRequestAsync(session,
new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
if (null != user) {
C.trace("user name: " + user.getName());
C.trace("user gender: " + user.asMap().get("gender"));
}
}
});
my graph result no email:
GraphObject{graphObjectClass=Map, state={"id":"10000xxxxxxx","first_name":"xxxx","username":"xxxxxx","timezone":x,"locale":"en_US","link":"https:\/\/www.facebook.com\/xxxxxx","name":"xxxxx","last_name":"xxxxx","gender":"male","education":[{"type":"xxxx","school":{"id":"xxxxx","name":"xxxxx"}}],"updated_time":"xxxxxxx"}}
i'm concern about the way i put permission. then i put basic info and email on session. and i don't know if this the right way.
UPDATE
here screenshot while request to facebook. even there is a friend list that i don't put on permission. and on my graph, still no email there.
This is well known issue ..... for some accounts facebook don't wanna return email even when the code is correct. could you please try with other accounts?
I think you've added the permissions after being authorized once. So check out what all permissions you've provided to this app here by clicking on the Edit.
If you find that email permission is not set, then you can logout of the app/remove the app from the settings and then login again; so that you can be authorized again with the email permission included.
For getting email from facebook, try it something like below.
String email = user.asMap().get("email").toString();
Textview mEmail = (TextView) findViewById(R.id.textView1);
mEmail.setText(email);
By using this above code i am successfully able to get the email of facebbok user. Try it and let me know if you still face any problem.

Firebase: How to keep an Android user logged in?

I'm using Firebase SimpleLogin to enable Email / Password authentication. Creation of users and subsequent login is all working fine. However, whenever I leave the app (even if only for a few seconds) the user is never logged in on my return i.e...
authClient.checkAuthStatus(new SimpleLoginAuthenticatedHandler())...
Always returns a null user.
I am not logging out the user via the API. Also I have set the number of days the user is logged in to 21 in the Firebase console.
I have seen mention of a remember-me param in the JS docs, but I can't see any equivalent for Android / Java.
Wondering if I'm missing anything in the docs or if it's not possible for Android?
Thanks for your help,
Neil.
Edit: Added code sample.
User creation....
public void registerUserForChat(final MyApplication application, String email, String password) {
Firebase ref = new Firebase(FIREBASE_URL);
SimpleLogin authClient = new SimpleLogin(ref);
authClient.createUser(email, password, new SimpleLoginAuthenticatedHandler() {
#Override
public void authenticated(com.firebase.simplelogin.enums.Error error, User user) {
if(error != null) {
Log.e(TAG, "Error attempting to create new Firebase User: " + error);
}
else {
Log.d(TAG, "User successfully registered for Firebase");
application.setLoggedIntoChat(true);
}
}
});
}
User login....
public void loginUserForChat(final MyApplication application, String email, String password) {
Log.d(TAG, "Attempting to login Firebase user...");
Firebase ref = new Firebase(FirebaseService.FIREBASE_URL);
final SimpleLogin authClient = new SimpleLogin(ref);
authClient.checkAuthStatus(new SimpleLoginAuthenticatedHandler() {
#Override
public void authenticated(com.firebase.simplelogin.enums.Error error, User user) {
if (error != null) {
Log.d(TAG, "error performing check: " + error);
} else if (user == null) {
Log.d(TAG, "no user logged in. Will login...");
authClient.loginWithEmail(email, password, new SimpleLoginAuthenticatedHandler() {
#Override
public void authenticated(com.firebase.simplelogin.enums.Error error, User user) {
if(error != null) {
if(com.firebase.simplelogin.enums.Error.UserDoesNotExist == error) {
Log.e(TAG, "UserDoesNotExist!");
} else {
Log.e(TAG, "Error attempting to login Firebase User: " + error);
}
}
else {
Log.d(TAG, "User successfully logged into Firebase");
application.setLoggedIntoChat(true);
}
}
});
} else {
Log.d(TAG, "user is logged in");
}
}
});
}
So loginUserForChat method first checks to see if there is a logged in user and, if not, performs the login. Note that every time I start the app, the logging I see is....
Attempting to login Firebase user...
no user logged in. Will login...
User successfully logged into Firebase
If I exit the app, even for a few seconds, and return - I see the same logging.
One thing I noticed is that the call to checkAuthStatus does not take any user credentials - I assume it just checks for any locally logged in user?
Much appreciated.
Another way - try this code in your onCreate:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is signed in
Intent i = new Intent(LoginActivity.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
This will keep the user logged in by taking the user to the Main activity directly without stopping at registration activity. so the user will be logged in unless the user click on signout.
[Engineer at Firebase] In order to transparently handle persistent sessions in the Firebase Simple Login Java client, you need to use the two-argument constructor which accepts an Android context, i.e. SimpleLogin(com.firebase.client.Firebase ref, android.content.Context context) every time you instantiate the Simple Login Java client.
See https://www.firebase.com/docs/java-simple-login-api/javadoc/com/firebase/simplelogin/SimpleLogin.html for the full API reference.
The proper way to do it is to use oAuth authentication:
1. The user logs in.
2. You generate an access token(oAuth2).
3. Android app saves the token locally.
4. Each time the comes back to the auth, he can use the token to to log in, unless the token has been revoked by you, or he changed his
password.
Luckily, firebase has an out of the box support for that, docs:
https://www.firebase.com/docs/security/custom-login.html
https://www.firebase.com/docs/security/authentication.html
You can do this by Using this Approach to escape logi page if User already logged in.
private FirebaseAuth auth;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
auth = FirebaseAuth.getInstance();
if (auth.getCurrentUser() != null) {
startActivity(new Intent(Login_Activity.this, Home.class));
finish();
}
setContentView(R.layout.activity_login_);
for those using Kotlin, to keep the user logged in just add in the onCreate function
if (auth.currentUser != null)
{
startActivity(Intent(this#Login, SellingPageHolderActivity::class.java))
finish()
}

Categories

Resources