How to retrieve the Json Information from the Provider on Firebase - android

I was looking on the Firebase SDK and I found that FirebaseUser has a method called
getProviderData()
that we can use to get some information about the provider in case that we are login with Google or Facebook.
But let's say I want to retrieve the FirstName and LastName instead of DisplayName also the Facebook email and some specific information that is not implemented on UserInfo.
I found a solution for Facebook which is requiring an additional rest call.
GraphRequest request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
try {
jsonResponseMap.put(USER_EMAIL, object.getString("email"));
jsonResponseMap.put(USER_FIRST_NAME, object.getString("first_name"));
jsonResponseMap.put(USER_LAST__NAME, object.getString("last_name"));
listener.onResult(jsonResponseMap);
} catch (JSONException e) {
e.printStackTrace();
listener.onError(e.getMessage());
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields","id, email, first_name, last_name");
request.setParameters(parameters);
request.executeAsync();
So the big question is that why make another call when Firebase is providing the json already.
Researching a little bit I found that Firebase SDK is implementing a class called
zzf which implement UserInfo and returning the json using
String getRawUserInfo().
Using the debugger I got this json from Google (Facebook has similar format):
Google
{
"azp": "86867144690-7vvjul4p96e143413484c5h9e.apps.googleusercontent.com",
"aud": "86813434690-o49lqnvo8c1232315rdrmi1ej9.apps.googleusercontent.com",
"sub": "103026921153548850697",
"email": "Steve.Jhon#gmail.com",
"email_verified": true,
"exp": 1520122390,
"iss": "https://accounts.google.com",
"iat": 1520128790,
"name": "Jhon Steve",
"picture": "https://lh6.googleusercontent.com/-4-WnMz5Fqoo/AAAAAAAAAAI/AAAAAAAAAAA/AGi4132322313SfRlc412L5tRvZJsOA/s96-c/photo.jpg",
"given_name": "Jhon",
"family_name": "Steve",
"locale": "en"
}
With this information, I want to ask you guys that...
How can I cast the zzf class to retrieve the proper raw information from the provider?

If you want additional user info after sign-in/sign-up, you can get it from AdditionalUserInfo on AuthResult.
It provides a getProfile API which returns a map<String, Object> with all provide related profile info.

Related

Firebase AuthUI - Fetch additional User Information from Facebook Provider

I'm trying to get the requested information from Facebook Provider of Firebase AuthUI.
I didn't find any method to get this data. When I debug that step, I can see the requested information in the attribute "zzdd" as JSON like.
How can I get this data?
Request birthday and gender information from user:
new AuthUI.IdpConfig.FacebookBuilder()
.setPermissions( Arrays.asList( "user_birthday", "user_gender" ) )
.build() );
Fetch data from provider
mUser = FirebaseAuth.getInstance().getCurrentUser();
for( UserInfo user : mUser.getProviderData() ) { }
Debbuger - user - zzdd attribute
{"birthday":"08/05/1995","updated_time":"2018-05-04T21:28:53+0000","gender":"male",...}
Firebase AuthUI Version: 3.3.1
I found the solution.
To get additional information by Firebase Auth you must get by SDK providers, like Facebook as code below:
Get data from Facebook SDK on Login Success with Firebase AuthUI:
GraphRequest request = GraphRequest.newMeRequest(
AccessToken.getCurrentAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted( JSONObject jsonObject, GraphResponse response ) {
// Application code
try {
String birthday = jsonObject.getString( "birthday" );
String gender = jsonObject.getString( "gender" );
} catch( JSONException e ) {
e.printStackTrace();
}
}
} );
Bundle parameters = new Bundle();
parameters.putString( "fields", "birthday,gender" );
request.setParameters( parameters );
request.executeAsync();

Issue signing into Amazon S3 with Google Sign-in on Android

I'm building an Android app that connects to an Amazon S3 bucket and retrieves mp3 files stored within. This is my first time using Google Sign-in, and it's for a (hopefully) production app, and I want to do it properly.
I've followed all the directions here and have successfully received an ID Token by calling GoogleSignInAccount.getIdToken().
I have then used Amazon's directions for OpenID Connect providers here and used this code:
// Initializing the Amazon Cognito credentials provider
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider (
getApplicationContext(),
"us-east-1:220fe85c-fcc9-4ecc-b923-1357e1380fde", // Example Identity Pool ID
Regions.US_EAST_1 // Example Region
);
Map<String, String> logins = new HashMap<String, String>();
logins.put("accounts.google.com", idToken);
credentialsProvider.setLogins(logins);
to login. However, nothing is showing up in my Identity Pool. I'm wondering whether it's some confusion on my part in regards to which Client ID I am using. When I created the project on the Google Developer console, I received two ID's. One for a Web Application, and one for Android.
As per Google's instructions here, I passed the Web client ID to the requestIdToken method when I created the GoogleSignInOptions object, and the Android ID to the Identity Pool, like this:
I removed all the other numbers after the hyphen, as the example calls for a smaller ID, but for the record, neither version works. The original was like:
1034544032360-77XXXkoq9XXkdXXsj82uhdXXXbqii6t2.apps.googleusercontent.com
Except when I test my app, It seems to be successful, no errors are thrown, but no new identities are logged in my identity pool.
What am I missing? I would really appreciate a nudge in the right direction.
Is that code you gave the extent of your logging in? The Cognito Android SDK gets credentials lazily, setting logins alone won't do anything. Try adding a credentialsProvider.refresh(); after that.
Okay, I solved it finally; there were a few things I missed.
Firstly, as Jeff Bailey mentioned, I wasn't calling credentialsProvider.refresh() after I had set the login token, like this:
private void setCredentials(String token) {
Map<String, String> logins = new HashMap<>();
logins.put("accounts.google.com", token);
credentialsProvider.withLogins(logins);
}
However, that method requires a network request, so that had to be called from an Async task.
Secondly, I used different code to get an ID token from Google, instead of GoogleSignInAccount.getIdToken. See below:
private class GetAndSetGoogleToken extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
try {
GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
AccountManager am = AccountManager.get(getApplicationContext());
Account[] accounts = am.getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
token = GoogleAuthUtil.getToken(getApplicationContext(), accounts[0].name,
"audience:server:client_id:" + serverClientId);
} catch(GoogleAuthException ex) {
Log.d(TAG, "GoogleAuthException has been thrown by GetAndSetGoogleToken!");
} catch(IOException ex2) {
Log.d(TAG, "IOException has been thrown by GetAndSetGoogleToken!");
}
return token;
}
#Override
protected void onPostExecute(String token) {
// Passing the ID Token as an Extra to the Intent and starting a new Activity.
goToNextActivity(token);
super.onPostExecute(token);
}
}
Finally, I hadn't modified my IAM Trust Policies to recognise accounts.google.com as a trusted entity. Once doing so, they looked like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": [
"cognito-identity.amazonaws.com",
"accounts.google.com" // I needed to add this
]
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:xxxx2e4a-4cf6-4121-aa16-xxxx53374a49"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
Having done all that, it worked fine.
Hope this helps someone; it doesn't seem to be a well documented use-case unfortunately.

Android - Oauth2, AccountManager and Google: retrieve profile data

I'm making an app that should allow the user to register through its google account. I want to retrieve automatically as many profile infos as I can. I found this very interesting example, which would allow me to get many infos (see step 4 of that demo). Now, how do I use it on android? I saw many examples of how to get the authentication token with the AccountManager with Oauth2 (example), but I don't know what to do from there to make those calls and retrieve those infos. Also in that example the code is in javascript and I don't know how to port it properly to java...
I have already done the google dev console registration stuff.
Are Oauth2 and OpenID the same thing? If not, do I have to use either one OR the other?
Ok, done. As expected, I found all the infos in the docs, and using Google's Oauth2 Playground helped to understand what to send to https://www.googleapis.com/oauth2/v1/userinfo in order to receive the profile data.
In the end, it turns out we don't need to create a client ID in google's dev console to do this.
Now, to the code. The activity:
public class MainActivity extends Activity {
public Activity mContext;
private AccountManager accountManager;
private final String SCOPES = "oauth2:https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile";
private String authToken;
private GetProfileDataTask googleTask;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
mContext = this;
accountManager = AccountManager.get(mContext);
//other stuff here...
}
public void getProfileData() {
accountManager.getAuthTokenByFeatures(
"com.google",
SCOPES,
null, mContext, null, null,
new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
//bundle.getString(AccountManager.KEY_ACCOUNT_NAME);
//bundle.getString(AccountManager.KEY_ACCOUNT_TYPE);
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
} catch (Exception e) {
System.out.println("getAuthTokenByFeatures() cancelled or failed:");
e.printStackTrace();
authToken = "failure";
}
if(!authToken.equals("failure")) {
googleTask = new GetProfileDataTask();
googleTask.execute(authToken);
}
}
}, null);
}
}
The AsyncTask that gets the data:
public class GetProfileDataTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... tokens) {
RestTemplate restTemplate = new RestTemplate(false);
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
String json = null;
try {
//the response is of type "application/json"
json = restTemplate.getForObject(
"https://www.googleapis.com/oauth2/v1/userinfo" +
"?access_token={token}" +
"&access_token_type=bearer",
String.class,
tokens[0]); //this is the authToken from before, obv
} catch(RestClientException er) {
Log.e("GetProfileDataTask", er.toString(), er);
json = null;
}
return json;
}
#Override
protected void onPostExecute(String asyncResult) {
if(asyncResult != null)
//do something with your data, for example deserialize it
else
//do something else
}
}
The received json is like this:
{
"family_name": "Smith",
"name": "John Smith",
"picture": "https://lh3.googleusercontent.com/-randomlettersandnumbers/AAAAAAAAAAI/AAAAAAAAAAA/morerandomlettersandnumbers/photo.jpg",
"locale": "it",
"gender": "male",
"email": "youremail#whatever.itis",
"link": "https://plus.google.com/133780085840848123456",
"given_name": "John",
"id": "133780085840848123456",
"verified_email": true
}
Since you want to allow user sign in your app via their Google accounts, you can use OpenID, and Google supports it.
Note: If you provide a “sign-in with Google” feature, we recommend using Google+ Sign-In.
If you just want get usr's info in Google on behalf of users, you can just use Oauth2. Refer to Google'a official documents, I think they are detailed, authoritative and easy to get along.
As this doc says:
5.Obtain user information from the ID token
An ID token is a cryptographically signed JSON object encoded in base 64. Normally, it is critical that you validate an ID token before you use it, but since you are communicating directly with Google over an intermediary-free HTTPS channel and using your client secret to authenticate yourself to Google, you can be confident that the token you receive really comes from Google and is valid.
So in a word, read these docs carefully and you'll get be clear about how to accomplish your app.

Send App request to all friends in Facebook using 'Requests Dialog' in Android

I want to know how to send app request to all my facebook friends from android app. I tried in graph API. But, couldn't get it done.
https://graph.facebook.com/apprequests?ids=friend1,friend2&message='Hi'&method=post&access_token=ACCESS_TOKEN
I know this is a Duplicate question. But, couldn't find an answer yet.
I'm getting this error on the above API.
"All users in param ids must have accepted TOS."
I hope there will be a way to send app request to all friends from mobile on a click. Please share it.
The error message you receive ("All users in param ids must have accepted TOS") is because you are trying to send an app generated request to a user who is not connected to your app.
See the developer docs here.
Requests sent with the request dialog and app generated requests are different and you can't use app generated requests to invite users to your app.
Sending Facebook app requests are not available via the graph api. You can use the app requests java-script dialog to send the request though, you would just need to specify the user's id in the "to" property as detailed in the documentation.
Sample function:
<script>
FB.init({ appId: '**appId**', status: true, cookie: true, xfbml : true });
function sendRequest(to) {
FB.ui({method: 'apprequests', to: to, message: 'You should learn more about this awesome site.', data: 'tracking information for the user'});
return false;
}
</script>
Then just wire an onclick for each image to something like onclick="return sendRequest('**friendId**');"
Also you can call this function in javascript: It will give you all friends with photos. Also group of friends who are currently using same app. You can send request to any of them.
function sendRequestViaMultiFriendSelector() {
FB.ui({
method: 'apprequests',
message: "You should learn more about this awesome site."
});
}
See Facebook Friend Request - Error - 'All users in param ids must have accepted TOS'
Have you seen demo of "Hackbook" in the developer.facebook.com ?
You can refer HACKBOOK APP REQUEST FROM HERE.
You can achieve to post the app request to only one friend by below code.
Code:
Bundle params = new Bundle();
JSONObject attachment = new JSONObject();
JSONObject properties = new JSONObject();
JSONObject prop1 = new JSONObject();
JSONObject prop2 = new JSONObject();
JSONObject media = new JSONObject();
JSONStringer actions = null;
try {
attachment.put("name", "YOUR_APP");
attachment.put("href", "http://www.google.com/");
attachment.put("description", "ANY_TEXT");
media.put("type", "image");
media.put("src", "IMAGE_LINK");
media.put("href", "http://www.google.com/");
attachment.put("media", new JSONArray().put(media));
prop1.put("text", "www.google.com");
prop1.put("href", "http://www.google.com");
properties.put("Visit our website to download the app", prop1);
/* prop2.put("href", "http://www.google.com");
properties.put("iTunes Link ", prop2);*/
attachment.put("properties", properties);
Log.d("FACEBOOK", attachment.toString());
actions = new JSONStringer().object()
.key("name").value("APP_NAME")
.key("link").value("http://www.google.com/").endObject();
} catch (JSONException e) {
e.printStackTrace();
}
System.out.println("ACTIONS STRING: "+actions.toString());
System.out.println("ATTACHMENT STRING: "+attachment.toString());
params.putString("actions", actions.toString());
params.putString("attachment", attachment.toString()); // Original
params.putString("to", "YOUR_FRIEND_FACEBOOK_ID");
Utility.mFacebook.dialog(getParent(), "stream.publish", params,new PostDialogListener());
public class PostDialogListener extends BaseDialogListener {
#Override
public void onComplete(Bundle values) {
final String postId = values.getString("post_id");
if (postId != null) {
Toast.makeText(getApplicationContext(), ""+getResources().getString(R.string.facebook_response_msg_posted), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), ""+getResources().getString(R.string.facebook_response_msg_not_posted), Toast.LENGTH_SHORT).show();
}
}
}
Above code works perfect if you want to post the Apprequest only on One friend's wall. If you want to post on all then you have to make asynckTask which runs for all the friends post and post App request on all walls.
Update
Here is the link in PHP that have done same work to send request to all Facebook friends.
And [here it is clearly explained3 that it is blocked by Facebook to send a Friend Request to more then 15-20 friends.
Now, you have to only one option to do it is, use above code in AsyncTask to send Friend Request to all Friends One-by-One.

Android get Facebook friends who have app downloaded

I am using the Facebook Android SDK. Is there an easy way to get a user's friends who have downloaded the app? For example, the app Draw Something implements this. I can't seem to find any information on this subject
I would guess that if it was possible, some extra information would be needed in the httppost to access this information.
* Note: since 3.14 version, me/friends will only return friends that also use the app, so below implementation is deprecated. See the new "Invitable Friends" or "Taggable Friends" APIs for alternatives.
Using the new Facebook SDK for Android (3.0) is very easy to get your user's friend list.
Following is the code:
private void requestFacebookFriends(Session session) {
Request.executeMyFriendsRequestAsync(session,
new Request.GraphUserListCallback() {
#Override
public void onCompleted(List<GraphUser> users,
Response response) {
// TODO: your code for friends here!
}
});
}
Nevertheless, in order to get the user's friends who are using your Facebook app is a little bit complicated (due to Facebook API documentation). But yes, it is possible.
First of all, create your request:
private Request createRequest(Session session) {
Request request = Request.newGraphPathRequest(session, "me/friends", null);
Set<String> fields = new HashSet<String>();
String[] requiredFields = new String[] { "id", "name", "picture",
"installed" };
fields.addAll(Arrays.asList(requiredFields));
Bundle parameters = request.getParameters();
parameters.putString("fields", TextUtils.join(",", fields));
request.setParameters(parameters);
return request;
}
Note that you need to insert the field "installed" in your request. I'm requesting the user picture path with the same request. Check your possibilities here.
Next, you can use above code to create your request and then get your friends:
private void requestMyAppFacebookFriends(Session session) {
Request friendsRequest = createRequest(session);
friendsRequest.setCallback(new Request.Callback() {
#Override
public void onCompleted(Response response) {
List<GraphUser> friends = getResults(response);
// TODO: your code here
}
});
friendsRequest.executeAsync();
}
Note that using this generic request, you don't receive a GraphUser list as response. You'll need following code to get the response as GraphUser list:
private List<GraphUser> getResults(Response response) {
GraphMultiResult multiResult = response
.getGraphObjectAs(GraphMultiResult.class);
GraphObjectList<GraphObject> data = multiResult.getData();
return data.castToListOf(GraphUser.class);
}
Now you can use your user's friend list, with the information if each of your friends use your Facebook app:
GraphUser user = friends.get(0);
boolean installed = false;
if(user.getProperty("installed") != null)
installed = (Boolean) user.getProperty("installed");
I implemented it in this way
Bundle params = new Bundle();
params.putString("fields", "name, picture, location, installed");
And during displaying of the items on the list,in the getView() method i did this
boolean b = jsonObject.getBoolean("installed");
if (b){
Log.d("VIVEK",jsonObject.getString("name"));
}
I hope this post helps you:
How can i get my friends using my facebook App with graph api asp.net
According to the Facebook SDK, the has_added_app field is deprecated and you should use the is_app_user

Categories

Resources