Google+ and AppEngine Authentication - android

I have an Android application with Google+ already setup and I was wondering if I could use this connection to authenticate with Google AppEngine endpoints.
Google sample code is:
settings = getSharedPreferences(TAG, 0);
credential = GoogleAccountCredential.usingAudience(this, ClientCredentials.AUDIENCE);
setAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
Tictactoe.Builder builder = new Tictactoe.Builder(
AndroidHttp.newCompatibleTransport(), new GsonFactory(),
credential);
service = builder.build();
So this is fine, but I'm doing authentication all over again. Can I leverage the PlusClient in any way to avoid creating further credentials?
Thanks

You can do the below steps to utilise your google plus sign to authenticate users for Google AppEngine endpoints:
1, Get the account name using google plus which will be in the step
String accountName = mPlusClient.getAccountName();
Now you dont have to use the account picker provided in the sample code as you go the account name through google plus
2, Save the account name from your above step to the sharedpreferences and to credential:
private void setAccountName(String accountName) {
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.commit();
credential.setAccountName(accountName);
this.accountName = accountName;
}
3, Create a client id for a web app to be used as audience. I guess this should be in the same project in api console where you have already created a client id for your android app. Set this web app client id as ClientCredentials.AUDIENCE value.
4,In your app engine project with cloud endpoints, for the allowed_client_ids argument of the #endpoints.api decorator or #endpoints.method decorator, supply both Android client ID and web client ID. You must also set the audiences argument for the #endpoints.api decorator to the web client ID.
5, In your android app, use the account name and audience details to create a google credentials object and pass it to your service object to call the required cloud endpoint
6, You can also add a user check in your app engine code to ensure a valid user is accessing
from google.appengine.ext import endpoints
current_user = endpoints.get_current_user()
if raise_unauthorized and current_user is None:
raise endpoints.UnauthorizedException('Invalid token.')
Since you have google+, you can also look up the emailid using the userinfo.email scope as given here . Also check these 2 posts for useful info : GCE with G+ and Oauth on GAE with google play services

Related

Using token of play-services-auth to authenticate with Google Analytics Data API in Android

I want to call Google Analytics Data API and Google Analytics Management API with Java client APIs.
In the example they use a service account configured in a json file.
As I'm integrating other Google APIs as well, I use Google Play Services Auth for authentication (with OAuth 2), therefore I already have an access token, which I want to use. But I have no idea how to pass it to the Google Analytics client.
I've tried it that way:
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(mContext);
String tokenString = GoogleAuthUtil.getToken(mContext,
account.getAccount(),
"oauth2:https://www.googleapis.com/auth/analytics.readonly");
AccessToken token = new AccessToken(tokenString,
// Set expiration time in one hour,
// as credentials are created every time
// this method is called.
new Date(System.currentTimeMillis() + 60 * 60 * 1000)));
Credentials credentials = OAuth2Credentials.newBuilder().setAccessToken(token).build();
ClientContext clientContext = ClientContext.newBuilder().setCredentials(credentials).build();
BetaAnalyticsDataClient client = BetaAnalyticsDataClient.create(BetaAnalyticsDataSettings.newBuilder(clientContext).build());
The problem is that the client context seems to have no default values and so I needed to feed it with all the information I don't know (and don't want to do it that way, as there are default values used, when I do not put my own client context. So I'd like to use the same default values as well). So this ends in an IllegalStateException (Missing required properties: defaultCallContext).
Is there a way to get a default client context and then just overwrite the credentials, or is there any other way to pass my own OAuth credentials?
The behavior is the same for Analytics Data and Management API by the way. So I guess the same solution will solve both problems.
Aorlinn,
The BetaAnalyticsDataClient reference documentation contains the following snippet that shows how to override credentials:
BetaAnalyticsDataSettings betaAnalyticsDataSettings =
BetaAnalyticsDataSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
.build();
BetaAnalyticsDataClient betaAnalyticsDataClient =
BetaAnalyticsDataClient.create(betaAnalyticsDataSettings);
Please let me know if this helps.

Firebase auth vs. GoogleAccountCredetial

I have an android app that can login with google account using GoogleAccountCredential that allows me communicate e.g. with Google Spreadsheet API.
see https://developers.google.com/sheets/api/quickstart/android
Now I would like to add functionality that communicate also with Firebase Database and I wonder if there is any way how to do it with just one sign-in method. see https://firebase.google.com/docs/auth/android/google-signin
Which one is better? Do I need both? Does user see "google sign-in dialog" twice? Can I somehow reuse some auth-objects to other method?
This is an old post but I have some apps That do this; specifically login to firebase then setup a credential to create and write to a google sheet using the api. This code assumes you have oauth correctly setup in the android project and on the developers console. You enable the api for sheets there as well.
once that is done get the google-services.json from the firebase console and place it in your android project.
private static final String[] SCOPES =
{SheetsScopes.SPREADSHEETS, SheetsScopes.DRIVE_FILE};
// used for spreadsheet access only
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(),Arrays.asList(SCOPES));
// set exponential backoff policy
mCredential.setBackOff(new ExponentialBackOff());
setCredentailAccount();
private void setCredentailAccount() {
if (mFirebaseUser != null) {
mCredential.setSelectedAccount(
new
Account(mFirebaseUser.getEmail(),getPackageName()));
Log.i(TAG, "getAcctPermission - account set");
} else {
Log.i(TAG, "getAcctPermission - account not set");
}
}
I also implemented a separate login activity that incapsulates the login for the app. There are plenty of code samples for a firebase login. The Google credential is what is passed into the task to do the spreadsheet stuff. Also The oauth screen on the Api console has credentials for sheets that need to be added.

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.

Error 401 Google-api-php-client verifing by server Android inapppurchase

I need to verify on my server each Android purchase that was made before by user in my Android APP.
I though that working with google-api-php-client it would be easy the authentication and managing of the token in server. But there aren't any sample, and yesterday Google published new version 0.6.3 providing in-app-purchases service.
I followed -> *code.google.com/p/google-api-php-client/wiki/OAuth2#Service_Accounts*
On my code.google.com/apis/console/ I pushed on, "Google Play Android Developer API" and I configured the "service account" in API Access.
From Android client APP, server recives the PACKAGE_NAME, PRODUCT_ID and purchase TOKEN.
My server code is the following:
require_once '../../src/Google_Client.php';
require_once '../../src/contrib/Google_AndroidpublisherService.php';
// Set your client id, service account name, and the path to your private key.
// For more information about obtaining these keys, visit:
// https://developers.google.com/console/help/#service_accounts
const CLIENT_ID = 'asdf.apps.googleusercontent.com';
const SERVICE_ACCOUNT_NAME = 'asdf#developer.gserviceaccount.com';
// Make sure you keep your key.p12 file in a secure location, and isn't
// readable by others.
const KEY_FILE = '../../asdf/privatekey.p12';;
$client = new Google_Client();
$client->setApplicationName({APP_PACKAGE_NAME});
// Set your cached access token. Remember to replace $_SESSION with a
// real database or memcached.
session_start();
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Load the key in PKCS 12 format (you need to download this from the
// Google API Console when the service account was created.
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/androidpublisher'),
$key)
);
$client->setClientId(CLIENT_ID);
$service = new Google_AndroidPublisherService($client);
$res = $service->inapppurchases->get({APP_PACKAGE_NAME},{APP_PACKAGE_NAME.PRODUCT_ID}, {PURCHASE_TOKEN});
var_dump($res);
The error showed is:
Google_ServiceException: Error calling GET https://www.googleapis.com/androidpublisher
/v1.1/applications/{APP_PACKAGE_NAME}/inapp/{APP_PACKAGE_NAME.PRODUCT_ID}/purchases
/{PURCHASE_TOKEN}: (401) This developer account does not own the application. in
/.../google-api-php-client/src/io/Google_REST.php on line 66 Call Stack: 0.0201
266376 1. {main}() ............
Token is correct, and I'm working with the same account in Google API Console(https://code.google.com/apis/console) and Google Developer Console (https://play.google.com/apps/publish/). I'm only using Service account api, and don't working with Client ID for web applications, and Simple API Access. For security I changed here some code values.
Could somebody help me to know what's wrong on my purchase server verification using Google API please?How I know the owner of my app? Have something to do with Google Apis new project, project domain, project number, project ID, etc...?
I think my problem was because I was trying to use Service Accounts with a Google Apps Gmail own account ( non #gmail.com account ).
I had to delegate domain-wide authority to my service account.
And I had to instantiate a Android Publisher Service as follows: ( only founded in Google Api Drive documentation ).
I added "sub" parameter programmatically in Google_AssertionCredentials like follows:
$auth = new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
'https://www.googleapis.com/auth/androidpublisher',
$key);
$auth->sub = "myown#email.com";
$client->setAssertionCredentials($auth);
The documentation in Google Play Android Developer API is very poor, and Google Support doesn't help, they redirects you to documentation. Google PHP developers even don't know how Service Accounts works.
In spite of having found the answer by myself, Google needs to improve all new Google Play In-app Billing API version 3.

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.

Categories

Resources