OAuth 2.0 with Google Analytics API v3 - oauth

I used to be able to query the Google Analytics API with my account's login & password.
Google is now using OAuth for authentication which is great...
The only issue is that I only need ONE access token.
I don't wanna allow other users to fetch THEIR analytics data.
I just wanna be able to fetch MY data.
Is there a way I can generate an access token only for my app or my analytics account?
I know such solutions exists... For instance, Twitter provides what they call a "single-user oauth" for apps that don't require a specific user to sign in.
One again, all I'm trying to accomplish here is to fetch MY OWN analytics data via the API.
Is there a way to properly do that?

I'm adding a PHP answer - you may be able to adjust or convert it to garb / ruby code.
You should be able to use Analytics with service accounts now. You will indeed have to use a private key instead of an access token.
Create an app in the API Console
Basically, you go to the Google API Console and create an App.
Enable Google Analytics in the services tab.
In the API Access tab, create a new OAuth ID (Create another client ID... button), select service account and download your private key (Generate new key... link). You'll have to upload the key to your web server later.
On the API Access page, in the Service account section, copy the email address (#developer.gserviceaccount.com) and add a new user with this email address to your Google Analytics profile. If you do not do this, you'll get some nice errors
Code
Download the latest Google PHP Client off SVN (from the command line svn checkout http://google-api-php-client.googlecode.com/svn/trunk/ google-api-php-client-read-only).
You can now access the Analytics API in code:
require_once 'Google_Client.php';
require_once 'contrib/Google_AnalyticsService.php';
$keyfile = 'dsdfdss0sdfsdsdfsdf44923dfs9023-privatekey.p12';
// Initialise the Google Client object
$client = new Google_Client();
$client->setApplicationName('Your product name');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
'11122233344#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($keyfile)
)
);
// Get this from the Google Console, API Access page
$client->setClientId('11122233344.apps.googleusercontent.com');
$client->setAccessType('offline_access');
$analytics = new Google_AnalyticsService($client);
// We have finished setting up the connection,
// now get some data and output the number of visits this week.
// Your analytics profile id. (Admin -> Profile Settings -> Profile ID)
$analytics_id = 'ga:1234';
$lastWeek = date('Y-m-d', strtotime('-1 week'));
$today = date('Y-m-d');
try {
$results = $analytics->data_ga->get($analytics_id,
$lastWeek,
$today,'ga:visits');
echo '<b>Number of visits this week:</b> ';
echo $results['totalsForAllResults']['ga:visits'];
} catch(Exception $e) {
echo 'There was an error : - ' . $e->getMessage();
}

Terry Seidler answered this nicely for php. I want to add a java code example.
Api console setup
Start by doing the required steps in the google api console as Terry explained:
Basically, you go to the Google API Console and create an App. Enable
Google Analytics in the services tab. In the API Access tab, create a
new OAuth ID (Create another client ID... button), select service
account and download your private key (Generate new key... link).
You'll have to upload the key to your web server later.
On the API Access page, in the Service account section, copy the email
address (#developer.gserviceaccount.com) and add a new user with this
email address to your Google Analytics profile. If you do not do this,
you'll get some nice errors
Get the necessary libraries
Download the google analytics java client from:
https://developers.google.com/api-client-library/java/apis/analytics/v3
Or add the following maven dependencies:
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-analytics</artifactId>
<version>v3-rev94-1.18.0-rc</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson</artifactId>
<version>1.18.0-rc</version>
</dependency>
Now for the code:
public class HellowAnalyticsV3Api {
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
public void analyticsExample() {
// This is the .p12 file you got from the google api console by clicking generate new key
File analyticsKeyFile = new File(<p12FilePath>);
// This is the service account email address that you can find in the api console
String apiEmail = <something#developer.gserviceaccount.com>;
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(apiEmail)
.setServiceAccountScopes(Arrays.asList(AnalyticsScopes.ANALYTICS_READONLY))
.setServiceAccountPrivateKeyFromP12File(analyticsPrivateKeyFile).build();
Analytics analyticsService = new Analytics.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(<your application name>)
.build();
String startDate = "2014-01-03";
String endDate = "2014-03-03";
String mertrics = "ga:sessions,ga:timeOnPage";
// Use the analytics object build a query
Get get = analyticsService.data().ga().get(tableId, startDate, endDate, mertrics);
get.setDimensions("ga:city");
get.setFilters("ga:country==Canada");
get.setSort("-ga:sessions");
// Run the query
GaData data = get.execute();
// Do something with the data
if (data.getRows() != null) {
for (List<String> row : data.getRows()) {
System.out.println(row);
}
}
}

You can use a refresh token. Store the refresh token in a db or secure config file, then use it to show the stats.
Google API Offline Access Using OAuth 2.0 Refresh Token will give you an idea of how to capture then store your refresh token.
See also Using OAuth 2.0 for Web Server Applications - Offline Access

Hello I found a solution, it works for me
you have to change this one
immediate: true
to
immediate: false
and it looks like
function checkAuth() {
gapi.auth.authorize({
client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
}

Google has the 'Service Account' (Calls Google APIs on behalf of your application instead of an end-user), but the way it works is a bit different as it won't use access tokens but a private key instead.
You can find more details at https://developers.google.com/accounts/docs/OAuth2ServiceAccount

Related

Error when querying Microsoft Graph API Shifts: "MS-APP-ACTS-AS header needs to be set for application context requests"

We are trying to query shifts in the Microsoft Graph API using a C# app, now that StaffHub got deprecated , in the past we were getting an Unknown Error which looked like a permissions issue.
In the docs I noticed permissions for Schedule.ReadAll and Schedule.ReadWriteAll so I added them to the application permissions in our App Registration in Azure.
Now when we send the request to https://graph.microsoft.com/beta/teams/{teamid}/schedule we get this error:
Microsoft.Graph.ServiceException: 'Code: Forbidden Message: {"error":{"code":"Forbidden","message":"MS-APP-ACTS-AS header needs to be set for application context requests.","details":[],"innererror":{"code":"MissingUserIdHeaderInAppContext"}}}
The documentation says the Schedule permissions are in private preview, are these required for querying a schedule & shifts, and if so, is it possible to request access to the private preview?
I'm in the same situation. It's possible to request private preview access (we have), but I'm guessing that it's primarily granted to Microsoft partners or at least have a connection at Microsoft.
The workaround for me has been getting access on behalf of a user. It does however require the user to enter username and password in order to get an access token, so it might not be a perfect solution for you. But it works. You need to add (and, I believe, grant admin consent for) delegated permissions for this to work, either Group.Read.All or Group.ReadWrite.All.
Edit:
I've got it working now. We have private preview access, so I'm not sure this will help you unless you do too, but as I understand it will be available eventually. Given your question, I presume you already have an access token.
Add MS-APP-ACT-AS as a header with the user ID of the user you want the Graph client to act as.
If you're using the Graph SDK for .NET Core you can just add a header to the authentication provider:
public IAuthenticationProvider GetAuthenticationProviderForActingAsUser(string userId, string accessToken)
{
return new DelegateAuthenticationProvider(
requestMessage =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
// Get event times in the current time zone.
requestMessage.Headers.Add("Prefer", "outlook.timezone=\"" + TimeZoneInfo.Local.Id + "\"");
requestMessage.Headers.Add("MS-APP-ACTS-AS", userId);
return Task.CompletedTask;
});
}
Then you call the graph service client:
var authenticationProvider = GetAuthenticationProviderForActingAsUser(userId, accessToken);
var graphClient = new GraphServiceClient(authenticationProvider);
You should then be able to fetch the shifts:
var shifts = await graphClient.Teams[teamId].Schedule.Shifts
.Request()
.AddAsync(shift);

Use Google Sheet Authentication for application, not for end user

I am trying to use Google Sheet in my application. This google sheet is not related to end user but will be under my own account. As per some tutorial on Google Sheets API I have created project on developer console but during OAuth 2.0 authentication, Google display login dialog to end user. As said before, this sheet is not related to end user so how can I fix my own Google credentials in code so that it just work with sheet, without asking user for his credentials?
Here is my code snippet
var clientSecret = new Google.Apis.Auth.OAuth2.ClientSecrets() { ClientId = "*******.apps.googleusercontent.com", ClientSecret = "*******" };
var credential = Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(clientSecret,
Scopes,
"myemail#google.com",
System.Threading.CancellationToken.None).Result;
var service = new Google.Apis.Sheets.v4.SheetsService(new Google.Apis.Services.BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
Are you looking to publish the article publicly?
https://support.google.com/docs/answer/37579?hl=en
You can use this method, then embed the sheet in an iframe on your site
It looks there are no such ways yet. So finally I decided to use local database and then export content to Excel using ClosedXML library.

Google My Business Requested entity was not found

I'm trying to implement an integration between a ERP system and Google My Business to keep store data in sync.
I have a project in the developer console. I have gained access to the GMB API and is approved by Google to use this API.
I'm using a serviceaccount and have followed the instructions from various guides.
But now I'm stuck.
I'm using the google GMB c# library to connect to GMB. I have a valid .12 file for my service account.
string MybusinessServiceScope = "https://www.googleapis.com/auth/plus.business.manage";
String serviceAccountEmail = "myserviceaccount#myapplication-1349.iam.gserviceaccount.com";
var certificate = new X509Certificate2(_serviceP12File, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { MybusinessServiceScope },
}.FromCertificate(certificate));
return new MybusinessService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "myapplication-1349",
});
When I try to List, Patch or Create locations I keep getting the same response:
Requested entity was not found. [404]
Errors [
Message[Requested entity was not found.] Location[ - ] Reason[notFound] Domain[global]
]
Any help is appreciated
I was unable to make this work with a service account. After talking to google support on the matter I change to use the OAuth application flow instead.
This works.
My chat with google: https://www.en.advertisercommunity.com/t5/Google-My-Business-API/Unable-to-PATCH-location-with-v3/td-p/579536#
Hope this can help others
this error occurs when the user doesn't have access to the provided location. (invalid access token or user access has been revoked etc)

Alternative of ClientLoginTokens

I am working on google Adwords API to upgrade our code for migration from v201302 to v201309.
Any one can suggest me, what code we should use in place of following code ( as ClientLoginTokens now deprecated).
String clientLoginToken = new ClientLoginTokens.Builder()
.forApi(ClientLoginTokens.Api.ADWORDS)
.withEmailAndPassword(configurations.get("email"), configurations.get("password"))
.build()
.requestToken();
Here are the steps that I took to get OAuth2 working. YMMV of course...
Step 1 - Register Application with Google Console API
Log into Google using your email and password above
Head to the Google API Console. You probably get redirected to Google Cloud Console
Under 'APIs & Auth' click on 'Consent screen'. Fill in at least 'Product Name' and 'Email'.
Under 'APIs & Auth' click on 'Registered apps'.
Click 'Register App'. Fill in details ensuring that you select 'Native' as platform.
Under 'OAuth 2.0 Client ID' make a note of the CLIENT ID and CLIENT SECRET values.
Step 2 - Generate Refresh Token
Next step is to generate a refresh token. This is a generate-once-use-multiple-times token that allows your application to obtain new access tokens:
Download GetRefreshToken.java.
Create an aps.properties file to be referenced by the GoogleClientSecretsBuilder()
.forApi(Api.ADWORDS) call. This ads.properties file should contain two lines:
api.adwords.clientId=client-id-from-step1.6
api.adwords.clientSecret=client-secret-from-step1.6
Using web browser log into the Google AdWords MCC.
Run GetRefreshToken.java and follow instructions i.e. copy browser URL into browser, enter code returned into console etc. etc.
You should now have a refreshToken. Copy this refresh token into your ads.properties files like this:
api.adwords.refreshToken=your-refresh-token
PS GetRefreshToken.java has a couple of dependencies. If you are using Maven then here they are (adjust versions accordingly!):
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-oauth2</artifactId>
<version>v2-rev50-1.17.0-rc</version>
</dependency>
<dependency>
<groupId>com.google.api-ads</groupId>
<artifactId>adwords-axis</artifactId>
<version>1.20.0</version>
</dependency>
Step 3 - Generate Credential
With your refreshToken, clientId & clientSecret in your ads.properties you can now generate a Credential like this:
Credential oAuth2Credential = new OfflineCredentials.Builder()
.forApi(Api.ADWORDS)
.fromFile()
.build()
.generateCredential();
Step 4 - Get AdWords Session
The final step (hats off to you if you have got this far!) is to create an AdWords Session using the oAuth2Credential instance of Credential that you created in Step 3. You can do this by adding two more things into your ads.properties file:
api.adwords.developerToken=developer-token-from-mcc
api.adwords.clientCustomerId=client-id-of-adwords-account-that-you-want-to-access
Then get an AdWords session up using like this:
AdWordsSession awSession =
new AdWordsSession.Builder()
.fromFile()
.withOAuth2Credential(oAuth2Credential)
.build();
Step 5 - Grab a coffee and reflect on how easy it is to access the Google AdWords API using OAuth2
This step is entirely optional.
You can not transform your old process identical as before. There are some examples in the Migration Guide from Google. See the Authentication/OAuth 2.0 section:
If you are coming from using ClientLogin, we've added a few features to make it extremely easy to switch over.
Once you've generated a refresh token using the GetRefreshToken.java example of your examples download, and you've copied it into your ads.properties file, you'll be able to create a refreshable token with the OfflineCredentials utility.
Credential oAuth2Credential = new OfflineCredentials.Builder()
.forApi(Api.DFP)
.fromFile()
.build()
.generateCredential();
Once authorized, you can set the Credential object into the builder or session:
DfpSession session = new DfpSession.Builder()
.fromFile()
.withOAuth2Credential(oAuth2Credential)
.build();
OAuth2 will now be used when making API calls.
You might change Api.DFP to Api.ADWORDS. OAuth 2.0 at Google is fully covered in the Using OAuth 2.0 for Login article.

How to import Google contacts in ASP.NET MVC (no third party please)

I have Used a API for importing the contacts of GMail. The code is something like this:
public static DataTable GetGmailContacts(string App_Name, string Uname, string UPassword)
{
Log.LogDebug(string.Format("SettingsController.cs-Importing Contacts for email={0}, password={1} from gmail server", Uname, UPassword));
DataTable dt = new DataTable();
DataColumn C2 = new DataColumn();
C2.DataType = Type.GetType("System.String");
C2.ColumnName = "EmailID";
try
{
dt.Columns.Add(C2);
RequestSettings rs = new RequestSettings(App_Name, Uname, UPassword);
rs.AutoPaging = true;
ContactsRequest cr = new ContactsRequest(rs);
Feed<Contact> f = cr.GetContacts();
foreach (Contact t in f.Entries)
{
foreach (EMail email in t.Emails)
{
DataRow dr1 = dt.NewRow();
dr1["EmailID"] = email.Address.ToString();
dt.Rows.Add(dr1);
}
}
Log.LogDebug(string.Format("SettingsController.cs-Imported Contacts for email={0}, password={1} from gmail server", Uname, UPassword));
return dt;
}
catch (Exception e)
{
dt = null;
Log.LogDebug(string.Format("SettingsController.cs-Imported Contacts for email={0}, password={1} from gmail server", Uname, UPassword));
return dt;
}
}
This code importing the GMail contacts but it is third party DLL. So some time Google warned me to not use it. So I want to use Direct API.
Versions 1 and 2 of the Google Contacts API have been officially deprecated as of April 20, 2012. They will continue to work as per our deprecation policy, but we encourage you to move to version 3
From: https://developers.google.com/google-apps/contacts/v2/developers_guide?hl=en
Authorizing requests with OAuth 2.0
Requests to the Google Contacts API for non-public user data must be authorized by an authenticated user.
The details of the authorization process, or "flow," for OAuth 2.0 vary somewhat depending on what kind of application you're writing. The following general process applies to all application types:
When you create your application, you register it with Google.
Google then provides information you'll need later, such as a client
ID and a client secret.
Activate the Google Contacts API in the Services pane of the Google
APIs Console. (If it isn't listed in the Console, then skip this
step.)
When your application needs access to user data, it asks Google for
a particular scope of access.
Google displays an OAuth dialog to the user, asking them to
authorize your application to request some of their data.
If the user approves, then Google gives your application a
short-lived access token.
Your application requests user data, attaching the access token to
the request.
If Google determines that your request and the token are valid, it
returns the requested data.
From: https://developers.google.com/google-apps/contacts/v3/#authorizing_requests_with_oauth_20
Check Google Contacts API v2 Developer's Guide - .Net and Google Contacts API version 3.0 to write your own code :)

Resources