How can I access the Google account user_id? - android

I'd like to access the user's Google account user_id for authentication, but I don't see any mention of this in the AccountManager.
How can my app request the user_id?

Now that Google Play Services is available, you can use it to request the user's permission to access the https://www.googleapis.com/auth/userinfo.profile scope and, with the resulting access token, make a request to https://www.googleapis.com/oauth2/v1/userinfo?access_token={accessToken} to get their user ID.

You will need to use the Android AccountManager's getAuthToken API until Google Play services is released.
Here's an example of how you can use getAuthToken to obtain an access_token: https://stackoverflow.com/a/10988589/313790

Check out Google's AccountManager example for the Tasks API.
Once you have an access token, you then instead of using the Tasks library, use the oauth2 library of google-api-java-client to request a Userinfo object like in this example:
Oauth2 oauth2 = new Oauth2.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("Google-OAuth2Sample/1.0").build();
Userinfo userinfo = oauth2.userinfo().get().execute();
String userId = userinfo.getId();

Related

Authorize YouTube Data API for Android via OAuth2

I am trying to authorize with OAuth2 to use YouTube data API. I want to write a simple client for Android to have a possibility, for example, get lists of user subscriptions, playlist etc.
The problem is that each method I try (e.g. HTTP requests like https://www.googleapis.com/youtube/v3/subscriptions or YouTube library com.google.apis:google-api-services-youtube:v3-rev120-1.19.0), I get the same error:
401 Invalid Credentials
I do these steps:
Register app in Google's console. Enable YouTube Data API. Create OAuth credentials with my app package name and keystore.
Create Android API Key.
And here I have a lot of questions.
To have a possibility to get user subscriptions etc. do I have to register the app with OAuth2 credentials AND (?) Register API Key?
How can I use client_id and other data that is in client_secrets.json? How can I use this client_secrets.json at all? Do I need download it, and how to use it?
Because when I saw sample code, for example this:
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(context.getApplicationContext(), Arrays.asList(SCOPES));
credential.setSelectedAccountName(accountName);
YouTube youtube = new YouTube.Builder(new NetHttpTransport(),
new JacksonFactory(), credential).setApplicationName(context.getString(R.string.app_name)).build();
Or used AccountManager and get token
accountManager.getAuthToken(userAccount, "oauth2:" + mScope, null, (Activity) mContext,
new OnTokenAcquired(), null);
where mScope="https://gdata.youtube.com"
and then use it this way
https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&maxResults=10&mine=true&key={here is my key}&access_token= ya29.bgJa5J8LHHu0Mu3P87mbPY9gfhSFzWUHh8gCw022FC6yfMO6GfVHveYr_BG1-HnWF-jpd-IDcGGVrF3gEf4UhSHPSrV76RAwqd4V17ixn72s1Xl6a0wQ4FVDz3cEZjUEN80o
I get the same authError error every time (in short):
"code": 401,
"message": "Invalid Credentials"
What I am doing wrong? How to use client_id in variant 1 and 2. Is it necessary? Because I think it is the reason why it does not work.

Google Cloud Endpoints custom Authentication

I am quite new to google cloud endpoints and I would like know how to Use Auth with Endpoints, the tutorial here is good, but I don't understand this thing:
It says, that I should add a user(com.google.appengine.api.users.User
) parameter to backend's methods for auth. If I want to use android as client part, I should provide GoogleAccountCredential object to make an authenticated call [2]. The GoogleAccountCredential is created this way
credential = GoogleAccountCredential.usingAudience(this,
"server:client_id:1-web-app.apps.googleusercontent.com");
credential.setSelectedAccountName(accountName);
The accountName is the name of a Google Account, so I assume, that everyone, who has the Google Account and is using my Google Cloud Endpoint application can create the GoogleAccountCredential object and make an authenticated call to backend.
But there are obviously many methods in my backend, which can be invoked only by some users of my app. (example: There is a method, which will give me a details about my friend, it's clear that this method can be called only by his friends.). Hence my question is: Is there any way to map the com.google.appengine.api.users.User to some my custom User entity, to be possible to check whether the User is really authorized to call the backend's method and not only to know that the method was called by a User with Google Account ? Should I write my custom Authenticator for this, if so, could you advise me how ?
Thank you!
You can set an Authenticator class which will handle the custom authentication.
https://cloud.google.com/appengine/docs/java/endpoints/javadoc/com/google/api/server/spi/config/Authenticator
you just need to set the authenticators param in the #ApiMethod and you can write your own authentication logic

accountmanager refresh token(offline access)

I use google login through account manager in my android app. I can get accesstoken which I send to server and server can create/login new user. Accesstoken is valid only 3600seconds. Problem is that server can not update user's info after this time expires. Web app requires check user's info periodically.
How can I get authentication token and refresh token from android account manager so than server can use refresh token to update data periodically? I don't want use login through webview in android app.
Thanks
This is now possible: https://developers.google.com/+/mobile/android/sign-in#server-side_access_for_your_app
You request a one-time authorisation code, send it to your server and your server exchanges it for an access token and refresh token.
Currently you can't, which I'm sure is not the answer you're hoping for, sorry about that! If you have a web sign in, you can use the hybrid flow to get a refresh token on the server as well (see https://developers.google.com/+/web/signin/server-side-flow), but there's no way of retrieving a code as part of the Android or iOS flows.
If this is something that you need for you use case, could you file a feature request on here: https://code.google.com/p/google-plus-platform/issues - we are actively looking at the number of stars on that to gauge demand for various features.
Google Authorization process through account manager:
Email id can be got from
AccountManager accountManager = AccountManager.get(getApplicationContext());
Account[] accounts = accountManager.getAccountsByType("com.google");
String emailID = accounts[0].name; // you can retrieve using google account chooser way also
These lines should be run in separate token(not in UI thread).
String scope = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://gdata.youtube.com";
String accessToken = GoogleAuthUtil.getToken(mContext, emailID, scope);
save the the accessToken and use for your api access.
After one hour (i.e. 3600 seconds), we need to refresh the access token. But now google is not supporting access after one hour. We have to restart the application and use the following lines to get access token.
String scope = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://gdata.youtube.com";
String accessToken = GoogleAuthUtil.getToken(mContext, emailID, scope);
This background thread will always run in background in while loop

Is it possible to authenticate user manually with oauth2

I want to authenticate a user with oauth2 to access google drive. I can get the access token required when using AccountManager to retrieve an account and then get the token with:
mgr.blockingGetAuthToken(account, ApiConst.DRIVE_AUTH_SCOPE, true);
But I want the user to be able to authenticate by providing username and password instead of using the account added to the phone. Is this possible?
EDIT
So I have tried to implement the authorization in a WebView. I followed this example. I have extracted the code request parameter but the code used to retrieve the access token seems to be deprecated and not compatible with the packages used by Google Drive SDK. This is the code used to retrieve the access token in the example:
AccessTokenResponse accessTokenResponse = new GoogleAuthorizationCodeGrant(new NetHttpTransport(),
new JacksonFactory(),
OAuth2ClientCredentials.CLIENT_ID,
OAuth2ClientCredentials.CLIENT_SECRET,
code,
OAuth2ClientCredentials.REDIRECT_URI).execute();
Can this be done in some other way or should I just give up?
If you are in Android, you don't nedd to do all that stuff to authenticate a user.
Just use "GoogleAccountCredential" object to set the user's account:
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(this, scopes);
credential.setSelectedAccountName(theGoogleAccount);
Remember that for select user's account you need:
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT);
Then you'll be able to initialize Drive:
Drive service = new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential).build();
Greetings.

Android subscription and Google API

I'm trying to use the new Android subscription system from Google Play into my application (I already had in-app billing working fine). I have successfully done the subscription billing, but I now want to retrieve informations about this subscription by using the google apis as indicated in the android documentation (http://developer.android.com/guide/market/billing/billing_subscriptions.html).
I want my service to be able to do the API call to retrieve these informations, but I have problems with authentication (with oauth2). So far, this is what I do (in my php service) :
require_once 'google-api-php-client/src/apiClient.php'
const SERVICE_ACCOUNT_NAME = 'email from services account access';
$key = 'content of my private key retrieved from services account access';
$client = new apiClient();
$cred = new apiAssertionCredentials(SERVICE_ACCOUNT_NAME, array('https://www.googleapis.com/auth/androidpublisher'), $key);
$assertion = $cred->generateAssertion(); // This generate my encrypted JWT
I then try to retrieve the access token with this JWT object. The problem is that when I use the access token given I got the error that the developer account does not own the application, which is not true.
(I know this is not the way to do it, but I just wanted to retrieve the access_token using the JWT to understand why it is not working, if I do it as indicated in the google apis documentation it is not working too).
I need to do this API call from a server, so no end-user has to be involved (no manual consent).
I had the same issue, and ultimately discovered that as of right now service accounts can not access the Play API.
I'm not sure when Google is planning on fixing this but you can get around this by creating a web app client ID and setting up a basic login page to first generate a code using the new web app Client data and going to $client->createAuthUrl():
$client = new apiClient();
$key = file_get_contents(KEY_FILE);
$client->setClientId(CLIENT_ID);
$client->setClientSecret(CLIENT_SECRET);
$client->setRedirectUri(MY_WEBAPP_URL);
$client->setDeveloperKey($key);
$client->setScopes(array('https://www.googleapis.com/auth/androidpublisher'));
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
This should take you to a Google login page where you should log in with the developer account. When you authorize the app, it will take you back to your web app URL as defined when you set up the client ID with a CODE as a get parameter. You can use to generate a token (and more importantly, a refresh token) like so:
$url = 'https://accounts.google.com/o/oauth2/token';
$fields = array(
'grant_type'=>'authorization_code',
'code'=>$code,
'client_id'=>CLIENT_ID,
'client_secret'=>CLIENT_SECRET,
'redirect_uri'=>MY_WEBAPP_URL
);
// cURL call to OAuth URL with $fields sent as POST
This should return you JSON data with a refresh token. Save this token and use it to make another call whenever you need to generate an access token. You will essentially run the same code you did to get the refresh token, but with different fields:
$fields = array(
'grant_type'=>'refresh_token',
'refresh_token'=>$refresh_token,
'client_id'=>CLIENT_ID,
'client_secret'=>CLIENT_SECRET,
);
This will give you an access token you can use to get purchase data from the following URL:
https://www.googleapis.com/androidpublisher/v1/applications/[PACKAGE]/subscriptions/[SKU]/purchases/[PURCHASE_TOKEN]?access_token=[ACCESS_TOKEN]
The trick is getting the refresh token, once you have that the rest should be pretty straightforward.
I`ve got the same problem. It occurs because you authorize user in Google API who does not own the application and try to get data which belows to your app.
In this topic it is well described. http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=2528691&topic=16285&ctx=topic
You should authorize by OAuth2 the owner of application, and then use Google API with obtained token.

Categories

Resources