I'm using this library https://code.google.com/p/socialauth-android/ to login into my application using google account. So far so good. I can get user name, email but get user profile picture. I think, that library uses OpenId + Oauth to login and after call:
profile.getProfileImageURL()
i get null.
I can get token and secret (OpenId ?) by calling:
socialAuthAdapter.getCurrentProvider().getAccessGrant()
For example:
token key : 1/J0_R-D03mykbqHnnNrVV1lk9FH2j996G05O2WVcHTrQ
token secret : vnh25rzUBVJKjHNpT_USeyjK
but i can't use this to retrieve user profile url by using link: https://www.googleapis.com/oauth2/v1/userinfo
Can you give me any tips, how to use what i get from this library to get also picture url ?
My oauth_consumer.properties:
www.google.com.consumer_key = xxxxx.com
www.google.com.consumer_secret = xxxxxxxxxx
www.google.com.custom_permissions = https://www.googleapis.com/auth/userinfo.profile
Apologies for the delayed response. We monitor socialauth questions on our Google project regularly.
The problem is that Google OpenId + OAuth api does not give image URL. We are in process of retrofitting the Google provider with Google+, so this will be available in the next minor release - star our Google project socialauth for updates.
Related
I am currently using Facebook login for firebase auth for my android app and retriving user's photourl using
firebaseAuth.getCurrentUser().getPhotoUrl()
This gives me the photo url from the user's facebook profile.
Recently I have received mail from Facebook stating -
"Facebook will now require client or app access tokens to access a user’s profile picture when querying against user IDs. Beginning on October 24, 2020, queries for profile pictures made against user IDs without an access token will return a generic silhouette rather than a profile picture."
More on it on this link https://developers.facebook.com/blog/post/2020/08/04/Introducing-graph-v8-marketing-api-v8
My question -
Does the request firebaseAuth.getCurrentUser().getPhotoUrl() use access tokens to access url from facebook and will it function the same after the release of Graph API 8.0 on 24th Oct?
Or will I have to make a different query request to fetch the User's photo url for facebook provider?
Unfortunately, you'll have to add the access token to the photo url by yourself as Firebase does not and will not support it (as they don't have access to it - you can read more about it here).
You'll have to do something along the lines of:
firebaseAuth.getCurrentUser().getPhotoUrl() + "?access_token=<facebook_access_token>"
To be able to get the access token of facebook, after being logged-in with Firebase, you can use:
AccessToken.getCurrentAccessToken()
Complementing the answer of Marek Fort, with Kotlin you can get the picture doing something like that:
"${firebaseAuth.getCurrentUser().getPhotoUrl()}?access_token=${AccessToken.getCurrentAccessToken()}"
In kotlin it looks like:
"${firebaseAuth.currentUser?.photoUrl}?access_token=${AccessToken.getCurrentAccessToken()?.token}"
I've been trying to add Google Sign-In in Android but have a couple of doubts.
From the Android documentation Integrate google sign in android
In the server side authentication part Client Id is required which is OAuth 2.0 web application client ID for your backend server.
From android's documentation:
Get your backend server's OAuth 2.0 client ID
If your app authenticates with a backend server or accesses Google APIs from your backend server, you must get the OAuth 2.0 client ID that was created for your server. To find the OAuth 2.0 client ID
From my understanding the flow would be:
Android app will get the auth code from google which will be passed to the backend.
The backend will get the access token with the auth code from the android app and the client secret.
With the acess token we get the user's information and the access token is saved in the database.
My doubts are:
I read somewhere on StackOverflow that we need to create two OAuth client one for Android and one for Web Application. Is this True?
Django Rest Auth Login View need to have one redirect_url defined but I don't understand what would be the redirect_uri in case of Android device or we need to pass this URL while getting the auth code from Google.
On OAuth Playground I put my backend's client id and client secret and got the auth code and when I passed this auth code to my login view I was getting the redirect_uri_mismatch but If I put redirect_url = 'developer.google.com' It works, I guess the auth code contains host information from where it is generated that's why this should be the same as redirect_url in my rest-auth view but then for android what it should be?
Here is my Google Login View.
class GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
client_class = OAuth2Client
callback_url = 'localhost:8000' # What this should be?
Please ask for more information If I forgot to put any.
I am using this
django-rest-auth
Some helpful link -
https://github.com/Tivix/django-rest-auth/issues/262#issuecomment-256562095 # It says callback URL could be a fake one but I get redirect_uri_mismatch
So Finally, I figured it out, Answering my own question so someone might find this helpful.
Yes, you need two client id one for your Android device and one for your web application.
Just add http://localhost:8000/accounts/google/login/callback/ as callback_url in the GoogleLoginView and put the same in your Google developer console.
I don't know exactly if the auth code generated by the Android contains any host information or not but it seems as long as the callback URL you added in the login view class and in google developer console is the same it will work.
Your Google sign in view should look like this.
class GoogleLogin(SocialLoginView):
authentication_classes = (JSONWebTokenAuthentication,)
adapter_class = GoogleOAuth2Adapter
callback_url = 'http://localhost:8000/accounts/google/login/callback/'
client_class = OAuth2Client
Note: You only need callback_url and client_class in case where you are passing the auth code to this view but if in you are passing the access_token then callback_url and client_class is not necessary.
I am an Android developer building my first Google App Engine (java) back-end for my apps. I don't want anybody else to access this API other than my app. (I plan to use App engine for verifying InApp purchases in my Android app). My data is not relevant to users so,
I don't want users to be able to access my API even if they are logged in with their Google accounts (on web or Android devices).
I followed the steps mentioned in - "Specifying authorized clients in the API backend"
(https://developers.google.com/appengine/docs/java/endpoints/auth)
like generating client IDs and add them in #Api (clientIds and audiences)
except "Add a User parameter" - since I don't need user authentication.
Then I deployed App engine and I am still able to access the API through API explorer (https://your_app_id.appspot.com/_ah/api/explorer)
(I haven't added API_EXPLORER client ID)
I tested with the APK that was built with the endpoint libs before adding client IDs and can still access the API.
Is adding a "User parameter" to all endpoint APIs a must? to achieve my purpose (restrict API to only my Android apps).
Can I pass null as userAccount name from Android client and ignore user parameter value on server (since it will be null)? Will this ensure that the API is accessible only from my android apps (since the client ID is generated for my package name and SHA1 of the APK?)
Should I use something like a service account for this purpose?
The documentation says for Android, both Android and Web client IDs must be added and audience must be the same as web client ID. Does this open access to any other web client? can I skip mentioning web client ID and still achieve my purpose?
Appreciate your time and help.
...... updating with my further investigation ...
I did the following:
Added User parameter to APIs on backend - but did not check for null value. API can still be accessed without passing any credentials (from Android debug APK and API explorer)
Then, I tried
mCredential = GoogleAccountCredential.usingAudience(this, "server:client_id:" + WEB_CLIENT_ID);
mCredential.setSelectedAccountName(null);
and passed this credential to API builder (as suggested in some other posts)
Caused FATAL EXCEPTION. So, we can't pass null account name.
I could call the API using API explorer without OAuth. But when I enabled OAuth, it gave error saying this client ID is not allowed! ( I haven't yet added com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID in client_ids{})
Then I added code to throw OAuthRequestException on the backend if the user is null. This resulted in API explorer getting errors without OAuth. It works with OAuth enabled after adding API_EXPLORER_CLIENT_ID to client_ids)
Added code to pass valid user account name(email) from my Android app. Then, I am able to access API only with my release APK. Even the debug APK gets exceptions! - which is what I expected..So, I assume no other Android apps will be able to access this API.
So, not checking for null user on back-end API is a bad idea (as suggested in other posts). It is as good as not mentioning any client_ids and not having User param.
Only question I have at this moment is: If some one can figure out the WEB_CLIENT_ID from the APK, will they be able to use it to build a web client to access my API (I haven't mentioned client secret anywhere in the code. So I am thinking this is not possible).
I did search Google groups and Stackoverflow, but still it is not clear.
(Authenticate my “app” to Google cloud endpoints not a “user”)
Authenticate my "app" to Google Cloud Endpoints not a "user"
(How do I protect my API that was built using Google Cloud Endpoints?)
How do I protect my API that was built using Google Cloud Endpoints?
(Restrict access to google cloud endpoints to Android app)
Restrict access to google cloud endpoints to Android app
I had a similar issue, not between Android and App Engine, but between a separate server and App Engine. The way I handled it was to add a signature hash field as a parameter to each API call. If the request had an improper signature, it would be denied.
For example, suppose your API end-point is example.com/api/do_thing?param1=foo. I would hash the entire url, along with a secret key, and then append the result of the hash to the request: example.com/api/do_thing?param1=foo&hash=[some long hex value].
Then, on the server side, I would first remove the hash from the url request, then run the hash on everything that was remaining. Finally, you check whether the calculated hash matches the one that was sent with the request and if they don't, you can deny the request.
It is very important however that your secret key remain secret. You have to be careful with this on Android because someone could attempt to decompile your APK.
Facing the same problem than you ! Authenticate Android End point without Google User Account is just impossible !
So here is my way to resolv this problem, without any user interaction (Maybe not the right but that works, and you've got strong authentication (SHA1 + Google Account)):
HERE IS MY ANDROID CODE
Get and Build Valid Credential
//Get all accounts from my Android Phone
String validGoogleAccount = null;
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
//Just store mail if countain gmail.com
if (account.name.toString().contains("gmail.com")&&account.type.toString().contains("com.google")){
validGoogleAccount=account.name.toString();
}
}
}
//Build Credential with valid google account
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(this,"server:client_id:301991144702-5qkqclsogd0b4fnkhrja7hppshrvp4kh.apps.googleusercontent.com");
credential.setSelectedAccountName(validGoogleAccount);
Use this credential for secure calls
Campagneendpoint.Builder endpointBuilder = new Campagneendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), credential);
HERE IS MY API BACKEND CODE:
API Annotation
#Api(
scopes=CONSTANTES.EMAIL_SCOPE,
clientIds = {CONSTANTES.ANDROID_CLIENT_ID,
CONSTANTES.WEB_CLIENT_ID,
com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {CONSTANTES.ANDROID_AUDIENCE},
name = "campagneendpoint",
version = "v1"
)
Method code:
public Collection<Campagne> getCampagnes(#Named("NumPortable")String NumPortable, User user) throws UnauthorizedException {
if (user == null) throw new UnauthorizedException("User is Not Valid");
return CampagneCRUD.getInstance().findCampagne(NumPortable);
}
For the moment, it only works on Android (I don't know how we gonna do on IOS..)..
Hope It will help you !
Google provides ways to do this for Android, web and iOS
The steps involves:
Specifying a client Id for apps you want to allow to make requests to your API
Adding a User parameter to all exposed methods to be protected by authorization.
Generating the client library again for any Android clients
Redeploying your backend API.
Updating the regenerated jar file to your Android project for your Android client.
These steps are laid out in clear detail on Google's Using Auth with Endpoints and also on this blog
Facing the same problem, here are the result of my research :
Added Android cliend id with SHA1 fingerprint in Google console
Use of it in the API annotation
BUT :
If i dont add user parameter to methods : the check about android app client id does not work
If I add the USER parameter but do not ask the user to choose its google account to create the credential ... also it does not work ...
Conclusion : It seems to be mandatory to connect a user account for the check about the app client id to be executed ... I really do not understand why because no link exist between the 2 processes
Access this site
Choose your project, go to credentials section
Create a new api key
Create a new android key
Click on "Edit allowed android applications" and enter your SHA1 key; your android package name
Let me know if this solves the issues.
how can i use oauth2.0 to get users google profile info on android app. I need the proper code/ example for an android app. I need the users information like :
profile photo
birthday
gender
location
Thanks
Google OAuth will require the following steps:
1.Register with Google here. after registering ,in the INSTALLED APPLICATION section you will get your REDIRECT_URI and CLIENT_ID
2.The REDIRECT_URI and CLIENT_ID obtained above now will be used in the following url.
https://accounts.google.com/o/oauth2/auth?" + "scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile"+ "&redirect_uri=" + REDIRECT_URI + "&response_type=code" +"&client_id=" + CLIENT_ID;
3.This url will take you to the Google Authentication page, here google takes over and you enter your account details. Further, it is redirected to the approval page, where the user allows your app to use their google data.
4.Now, as a response to this you get ACCESS CODE from google as a JSON or in the title of the html page. Parse the ACCESS CODE.
5.With the ACCESS CODE you will now make a POST request with the following post data to get the ACCESS TOKEN.
'code' // this is the access code
'client_id' // same as earlier
'client_secret' // you will find this on the google page where you registered
'redirect_uri' // same as earlier
'grant_type' = "authorization_code" // as is
6.You will now get the ACCESS TOKEN in a JSON as "access_token" . parse this access token.
7.Make use of the Access token to make a call on the following url
https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=your_access_token_here
8.You will get the users data as a response to this call as a JSON.
Here are additional docs that you may need:
https://developers.google.com/accounts/docs/OAuth2InstalledApp
We have developed and published an app for Google Health. Now we want to avoid every time logging into the gmail account by asking username and password.
So as to do this i have heard that I can have following options.
1. OAuth
2. Account Manager
3.
The problem with OAuth is that it will go via Android -> Web App -> Health path so i will need to develop an web app as well which we dont wish to do it right now.
So I am trying to use Account Manager, here is my code with which I could get list of accounts and an valid authToken for the selected account.
AccountManager mgr = AccountManager.get(getApplicationContext());
System.out.println("Got account manager");
Account[] accts = mgr.getAccounts();
}
Account acct = accts[0];
AccountManagerFuture<Bundle> accountManagerFuture = mgr.getAuthToken(acct, "android", null, this, null, null);
Bundle authTokenBundle = accountManagerFuture.getResult();
System.out.println("Account name "+accts[0].name);
String authToken = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();
System.out.println("Got token:"+authToken);
But now I am confused about how to use this token to access the health data.
For getting the demographic feed we used the following code,where we explicitly made user to login into our application.
String queryURL = "https://www.google.com/health/feeds/profile/ui/" + profileId +"/-/DEMOGRAPHICS";
getDemoGrInfoQuery = new Query(new URL(queryURL));
Feed dempGrResultFeed;
globals = new Globals();
dempGrResultFeed = healthService.query(getDemoGrInfoQuery, Feed.class);
And thus we used to get the Feed using the URL.
And now I want to skip the login process and use the above authToken for retrieving the feed. How can this be done?
Any help would be really appreciated!!!
Thanks in advance,
As the standard OAuth procedure is supposed to work, you open the OAuth URL in a WebView (or anything similar) with all the required parameters, users provide Google (not your app) with their user name and password, then google gives you a token which you can use for your future communications.
This way the user doesn't have to give you their login credentials. They give it only to google, and google gives you a token which will authenticate your app every time you use it.
I think you should be good to go with this, since it requires you to open a WebView only once, unless the user logs out of google using your application or denies access to your application.
After getting the token, you just start polling google with that token and never ask user for their login credentials. quite seamless.
UPDATE
After our conversation in chat, let me tell you that you'll have to register an application with google, which will give you an appID, this appID will be used by your Android app to tell google that it is requesting permission on behalf of the Application which this appID refers to.
UPDATE 2
open the Google OAUth with all the parameters, google will give you a code
use that code and create a POST request again to google, and google will now return a long lasting AccessToken
You can then use this AccessToken in all your future communications