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.
Related
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.
So, I've implemented Firebase Auth & AuthUI and successfully used the Google auth provider to log in a user.
However, now I'm trying to access the Google APIs but I'm getting a login error when I try to access them. Code below is attempting to connect to Google Fit.
val account = GoogleSignIn.getAccountForExtension(requireContext(), fitnessOptions)
Fitness.getHistoryClient(requireContext(), account)
.readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener { r ->
val first = r.dataPoints.first()
...
}
.addOnFailureListener { e ->
...
}
at which point I'm getting an error message of:
com.google.android.gms.common.api.ApiException: 4: The user must be signed in to make this API call.
I've debugged the Firebase Auth process and can see that there are two providers on the current FirebaseUser, one Google & one Firebase which looks like rather than authing my app with Google, Firebase is authing itself, then authing my app with Firebase.
I'm pretty sure I can remove AuthUI and manually do the Google SSO implementation (per Google's docs) but I really don't want to as I plan on having pretty much all the Auth providers enabled and I don't want to have to code them all manually (not to mention doing all the layout etc)
So, if anyone knows how to access the Google APIs/signed in Google Account from the Firebase authed user, I'd love to hear it!
Thanks in advance for any help you can render!
Ok, I figured it out. Firebase doesn't pass any default scopes to the Google sign in provider. Fixed it by doing
...
AuthUI.IdpConfig.GoogleBuilder()
.setScopes(listOf(Scopes.FITNESS_ACTIVITY_READ)
...
to access the standard steps read information. You can find out which scopes you need here and reverse-engineer it's name in the Scopes class from there.
Hope that helps!
I am working on creating a web/app for my company (in my free time) to provide access for our customers to retrieve and reply to google reviews for apps we have published for them.
Google has released a Reply to Reviews API which should work for this.
I haven't been able to figure out the Gaining Access portion.
I'm trying to use a service account. I've created an OAuth2 service account, granted access, downloaded a private key, and tired to follow the sample provided here (below).
I know that in the example it is using a Plus service.
My questions are, what service am I supposed to be using? I'm assuming the plus service is not what I want.
Is generating a certificate this way the correct way to get the auth_token (in the Reply to Reviews API documentation)?
Thanks for your help!
using System;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Plus.v1;
using Google.Apis.Plus.v1.Data;
using Google.Apis.Services;
namespace Google.Apis.Samples.PlusServiceAccount
{
/// <summary>
/// This sample demonstrates the simplest use case for a Service Account service.
/// The certificate needs to be downloaded from the Google Developers Console
/// <see cref="https://console.developers.google.com/">
/// "Create another client ID..." -> "Service Account" -> Download the certificate,
/// rename it as "key.p12" and add it to the project. Don't forget to change the Build action
/// to "Content" and the Copy to Output Directory to "Copy if newer".
/// </summary>
public class Program
{
// A known public activity.
private static String ACTIVITY_ID = "z12gtjhq3qn2xxl2o224exwiqruvtda0i";
public static void Main(string[] args)
{
Console.WriteLine("Plus API - Service Account");
Console.WriteLine("==========================");
String serviceAccountEmail = "SERVICE_ACCOUNT_EMAIL_HERE";
var certificate = new X509Certificate2(#"key.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { PlusService.Scope.PlusMe }
}.FromCertificate(certificate));
// Create the service.
var service = new PlusService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Plus API Sample",
});
Activity activity = service.Activities.Get(ACTIVITY_ID).Execute();
Console.WriteLine(" Activity: " + activity.Object.Content);
Console.WriteLine(" Video: " + activity.Object.Attachments[0].Url);
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
My questions are, what service am I supposed to be using? I'm assuming the plus service is not what I want.
To work with the Reply to Reviews API, you provide authorization using either an OAuth client or a service account.
So there are two ways.
Using OAuth2: Installed application
Edit the /resources/client_secrets.json file and add the client ID,
client secret and redirect uris. Execute any sample class using its
main() method to begin the auth flow:
A browser window will open and ask you to login. Make sure the account
has appropriate permissions in the Google Play Developer console.
Accept the permissions dialog. The browser should display The
authentication flow has completed. Close the window and go back into
your IDE and check the console output. The script will output a list
of apks. The tokens will be stored in .store/android_publisher_api in
your home folder. Remove this file to restart the auth flow.
using OAuth2: Service accounts Edit ApplicationConfig.java and add the service account email address. Copy the service account key
file, generated in the Google APIs Console into the same directory and
rename it to key.p12. Execute any sample class using its main() method
in your IDE The script will output a list of apks.
Here's a full sample in Github.
You need to use Google Android Publisher API for access to reviews and reply to them.
https://developers.google.com/android-publisher/reply-to-reviews#retrieving_reviews
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
I'm using Google AppEngine, and I'm using their UserService class to handle user accounts and logging in. I don't need to access any information about their account - I'm just using it to differentiate users.
Now the website is mostly just a backend. I'm using an Android app for the frontend. I know you can access Google user accounts on the device using the AccountManager. It's definitely the safest way to get a user to log in. And I got that much to work.
Where I'm stuck is passing the login information from the Android app to the AppEngine website. From what I've ready I should be using OAuth, and I see the walkthrough here for using it with Google APIs, but I don't need to access an API, just to log in. I've been able to acquire an Authentication Token in the app, but I'm not sure how to pass it to the website, or if that's even the right direction. Should I be using a specific OAuth login on the server, like this guy?
Any help would be greatly appreciated!
Here's the relevant code:
Server (GAE):
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
if (user == null) {
resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
return;
}
Client (Android):
AccountManager am = AccountManager.get(this);
Account[] accounts = am.getAccountsByType("com.google");
Bundle options = new Bundle();
am.getAuthToken(
accounts[0], // Account retrieved using getAccountsByType()
"Manage your tasks", // Auth scope
options, // Authenticator-specific options
this, // Your activity
new OnTokenAcquired(), // Callback called when a token is successfully acquired
new Handler(new OnError()));
//Now what!?
This blog post covered exactly what I needed.
For two alternate (and in my opinion less than ideal) solutions, check out this thread: Webservice credentials - OpenID/Android AccountManager?