I am trying to setup login on my app using facebook. Currently I have the SDK working fine, it authenticates and I can accession user information and then I start an Intent to my activity. (not sure if this is what I should be doing)
Now I am wondering what the workflow is for this is to authenticate with my RestAPI.
I can post the facebook_id to my server and add to my users database but I then read that I should be using the AccessToken, but how do I know if this is the correct AccessToken for that user?
What should be the flow here? Where should I be posting to the server and what should I be posting for every request in every Activity?
Here is my code I currently have.
private Session.StatusCallback statusCallback = new Session.StatusCallback() {
#Override
public void call(final Session session, SessionState sessionState, Exception e) {
if (sessionState.isOpened()) {
Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser graphUser, Response response) {
if (graphUser != null) {
Log.w(TAG, graphUser.getFirstName() + ' ' + graphUser.getId());
Log.w(TAG, session.getAccessToken() + ' ' + session.getExpirationDate());
Intent intent = new Intent(LoginActivityFragment.this, MainActivity.class);
startActivity(intent);
}
}
}).executeAsync();
} else if (sessionState.isClosed()) {
}
}
};
You should use the user ID as the unique identifier. The access token can change under many situations (updated permissions, user log in/out, etc), and should not be used to identify someone. The user ID will remain stable within your app.
You can send the access token along with the ID to your server, perhaps to make some FB requests from the server side, but that's a separate issue.
Related
I perform API call with Retrofit2 to login user via Firebase Authentication with email and password and after that need to interact somehow with user object, i.e. refresh some data or check if user logged in on next time application starts (I'm getting a correct Json object).
But after API call checking FirebaseAuth object mAuth.getCurrentUser() gives null and have no idea how to save login state inside my app.
NetworkService.getInstance().getJsonApi()
.loginWithEmail(email, password, true)
.enqueue(new Callback<Transaction.Result>() {
#Override
public void onResponse(Call<Transaction.Result> call, Response<Transaction.Result> response) {
if (response.code() == 200) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();
activity.updateUI(user);
activity.startService();
} else {
Log.d(TAG, "signInWithEmail:failure");
activity.showToast("Authentication failed.");
activity.updateUI(null);
}
activity.hideProgressBar();
}
#Override
public void onFailure(Call<Transaction.Result> call, Throwable t) {
t.printStackTrace();
}
});
How to retrieve FirebaseUser correctly?
Thanks.
If you're using the Firebase Auth REST API to sign in a user, you can't also use the Firebase Auth SDK to manage that sign-in. You will have to stick to using the REST API for all management. This means that you'll have to track the ID token that you get from the API, refresh the token every hour before it expires, and maintain your own sense of what it means for the user to be "signed in".
I highly suggest just using the provided SDK, as it will do all of this for you automatically.
I've been trying to set up a google login for my app.
I followed the tutorial here:
https://developers.google.com/identity/sign-in/android/start-integrating
I did everything. I can sign in sign in and sign out.
Then I added an Async task to get a token, which it seems to successfully retrieve. It is implemented as follows:
private class GetIdTokenTask extends AsyncTask<Void, Void, String> {
private static final String SERVER_CLIEdNT_ID = "749433126040-ca4gfj7ucuh0m2suo3230u03o3d7doni.apps.googleusercontent.com";
#Override
protected String doInBackground(Void... params) {
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
Account account = new Account(accountName, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
String scopes = "audience:server:client_id:" + SERVER_CLIEdNT_ID; // Not the app's client ID.
try {
return GoogleAuthUtil.getToken(getApplicationContext(), account, scopes);
} catch (IOException e) {
Log.e(TAG, "Error retrieving ID token.", e);
return null;
} catch (GoogleAuthException e) {
Log.e(TAG, "Error retrieving ID token. Google exception", e);
return null;
}
}
#Override
protected void onPostExecute(String result) {
Log.i(TAG, "ID token: " + result);
if (result != null) {
idToken = result;
Toast.makeText(context, "token is " + result, Toast.LENGTH_LONG).show();
} else {
// There was some error getting the ID Token
// ...
Toast.makeText(context, "token is null", Toast.LENGTH_LONG).show();
}
}
}
So after running the method and getting the token, I then run the generic firebase code to connect to Firebase (having already set up a google app, put the client ID in firebase, enabled it etc.) I got the code from https://www.firebase.com/docs/android/guide/login/google.html
And implemented it as follows:
public void loginFireBase() {
Firebase ref = new Firebase("https://boiling-fire-944.firebaseio.com");
ref.authWithOAuthToken("google", idToken, new Firebase.AuthResultHandler() {
#Override
public void onAuthenticated(AuthData authData) {
// the Google user is now authenticated with your Firebase app
Toast.makeText(context, "user succesfully authenticated with firebase", Toast.LENGTH_LONG).show();
Toast.makeText(context, idToken, Toast.LENGTH_LONG).show();
}
#Override
public void onAuthenticationError(FirebaseError firebaseError) {
///////THIS IS THE PART WHERE THE ERROR IS GENEREATED FROM//////////
Log.v("firebase problem", firebaseError.toString());
Toast.makeText(context, "I'm an authenticated error" + "id Token was " + idToken, Toast.LENGTH_LONG).show();
}
});
}
}
So ultimately, I login, I get a token, and then pass it to the firebase authWithOAuthToken method, and then I get the error:
FirebaseError: Invalid authentication credentials provided.
Can anyone see any problems in my code? I have a feeling the token is not valid but can't find a way to check its validity.
Tell me if you need me to post more, I was trying to keep it brief.
Thanks to anybody who can help !
Whenever I need to authenticate with Firebase on Android, I go back to the Firebase Android login demo. Here's how that app gets the OAuth token for Google authentication:
String scope = String.format("oauth2:%s", Scopes.PLUS_LOGIN);
token = GoogleAuthUtil.getToken(
GoogleOAuthActivity.this,
Plus.AccountApi.getAccountName(mGoogleApiClient),
scope);
It looks like you're getting the cross-client id for the user, which is not a valid OAuth token.
Update (20160308): nowadays I instead look at the FirebaseUI library, which includes this functionality and is more up to date.
In my case i was having this error message in Firebase/Crash
the solution was run this line:
rm $HOME/Library/Preferences/com.google.SymbolUpload*
this was happening because previously already had generated the ServiceAccount.json file and restart the credentials needed
I have an Android app with parse login with Facebook that works just fine… I´m building a new version of the app in which the app has the capability to do share to a Facebook Page, as the page. This is my code:
this is the code to request the list of pages the user manages
final Session session = Session.getActiveSession();
List<String> PERMISSIONS = Arrays.asList("publish_actions, publish_pages, manage_pages,user_about_me");
Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(activity,PERMISSIONS);
session.requestNewPublishPermissions(newPermissionsRequest);
new Request(
session,
"/me/accounts",
null,
HttpMethod.GET,
new Request.Callback() {
public void onCompleted(Response response) {
/* handle the result */}
Once selected a page, the link share is done by:
final String id = json_obj.getString("id");
String token = json_obj.getString("access_token");
Date date = new Date(3600);
List<String> PERMISSIONS = Arrays.asList("publish_actions, publish_pages, manage_pages,user_about_me");
final Bundle params = new Bundle();
params.putString("message", message);
params.putString("access_token", token);
params.putString("link", link);
params.putString("picture", image);
new Request(
session,
"/" + id + "/feed",
params,
HttpMethod.POST,
new Request.Callback() {
public void onCompleted(Response response) {
/* handle the result */}
The code works just fine, the link is posted to a Facebook Page, as the facebook page.
The problem comes when the user logs off and tries to log back in with facebook. Parse log in fails, without error message, and returns a null user. The weird thing is that this keeps on happening the particular device where the code was run, matter what user tries to login, or even if we uninstall the app and install a previous version which was working perfectly.
So far I’ve tested with three different devices and I get the same result, everything works fine before doing the facebook share as page. After that, no matter what user or what version of the app I run, the parse facebook log in fails returning a null user.
Ok, I found the what the issue WAS...
They way I had the code, it would ask for facebook permissions several times, and that would somehow mess up the user on facebook
In my app I am using Parse.com and Facebook login, and the Facebook login is working and I am now trying to save the email of the user who signed. I am doing this like this:
Request.newMeRequest(ParseFacebookUtils.getSession(), new Request.GraphUserCallback() {
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null) {
String email = user.getProperty("email").toString();
Log.i(TAG, email);
ParseUser currentUser = ParseUser.getCurrentUser();
currentUser.put("email", email);
currentUser.saveInBackground();
}
}
}).executeAsync()
But then when I run I get java.lang.NullPointerException at this line currentUser.put("email", email); But I log email before this and it is not null and I have a email attribute in my User class on parse, so Im not sure why this?
Here the code that comes before to set up the FB Login you should need it and it is working but just in case.
public void onLoginClick(View v) {
progressDialog = ProgressDialog.show(LoginActivity.this, "", "Logging in...", true);
final List<String> permissions = Arrays.asList("public_profile", "email");
// NOTE: for extended permissions, like "user_about_me", your app must be reviewed by the Facebook team
// (https://developers.facebook.com/docs/facebook-login/permissions/)
ParseFacebookUtils.logIn(permissions, this, new LogInCallback() {
#Override
public void done(ParseUser user, ParseException err) {
progressDialog.dismiss();
if (user == null) {
Log.d(TAG, "Uh oh. The user cancelled the Facebook login.");
} else if (user.isNew()) {
Log.d(TAG, "User signed up and logged in through Facebook!");
showSelectSchoolActivity();
} else {
Log.d(TAG, "User logged in through Facebook!");
showMainActivity();
}
}
});
Thanks for the help :)
for checking the response you should always use (err==null) as the condition for success. Only after you have recieved the response from the server and err==null then you can check for current user. You should also have a check for when err!=null. Then get the error message from the err.getCode() and check what the error code is.
I have been battling this problem for hours now and I seem to get nowhere with it. So, I have successfully asked the users to login using Facebook to my android app.
Once they are logged in, I get the access token (a string value) and then use it to make a Request to Facebook to fetch a Page's Posts. Here is how I do that whole process.
public void setupFacebook()
{
Session.openActiveSession(this, true, new Session.StatusCallback()
{
// callback when session changes state
#Override
public void call(Session mSession, SessionState state, Exception exception) {
if (mSession.isOpened() && mSession != null)
{
facebookAccessToken = mSession.getAccessToken();
Log.d("ACCESSTOKEN", facebookAccessToken);
fetchPagePosts(facebookAccessToken, mSession);
}
}
});
}
public void fetchPagePosts(String token, Session session)
{
Request.Callback callback = new Request.Callback()
{
#Override
public void onCompleted(Response response)
{
Log.d("RESPONSE", "ERROR"+response.getError());
Log.d("RESPONSE", ""+response);
}
};
String endpoint = String.format("https://graph.facebook.com/"+pageId+"/posts?access_token=%s", facebookAccessToken);
Log.d("ENDPOINT", endpoint);
Request request = new Request(session, endpoint, null, HttpMethod.GET, callback);
RequestAsyncTask task = new RequestAsyncTask(request);
task.execute();
}
The interesting part here is that when I copy the url from my Logcat (what I called endpoint) and paste to my browser, it works perfectly fine.
When I run my code on my tablet though, it returns the ErrorCode 190 and HttpStatus 400.
According to Facebook's documentation, it could be one of several things;
Access token is invalid
It is expired
The user has changed their password or
The user has logged out of their account
The user has revoked access to their account by your app!
I am stuck here because I have tested the same URL on the browser and it returns the json data I need. It just fails when am running it in android code.
If anyone has suggestions, please help me - will be truly thankful for your help.
Thank you in advance.
You could try using the Simple Facebook Android library instead of the Facebook SDK https://github.com/sromku/android-simple-facebook, its a lot simpler.