Google API Client Library freezing up in IIS when making request - asp.net-mvc

I have been using the Google API Client Library for .NET for loading Google Analytics data into my application:
Recently though I have found it to have started freezing up completely. The Execute() command makes a connection to the Google server.
It makes a successful request to :
https://accounts.google.com/o/oauth2/token
which returns something like :
{
"access_token" : "ya30.HAKlQSGZo2GnK5wxlxx9TLTQUyD9Xkt7AZxuQnDY-KhJuCyrCtN_xHIP",
"token_type" : "Bearer",
"expires_in" : 3600
}
But then never returns from the Execute call.
The same code in a console app returns immediately, but in IIS it is currently never returning.
In a previous version it worked just fine (I'm not exactly sure which version it changed).
I have Load User Profile set to true.
What could be causing this?
var SERVICE_ACCOUNT_PKCS12_FILE_PATH = #"C:\TEMP\GoogleAnalytics-privatekey.p12";
X509Certificate2 certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
// Create credentials (not my real login here)
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer("86987278011-ctegcus4og7kn6oigkrv8po5pf67bbgj#developer.gserviceaccount.com")
{
Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly }
}.FromCertificate(certificate));
// Create the service
var service = new AnalyticsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Google Analytics Application",
});
// get accounts
accounts = service.Management.Accounts.List();
var items = accounts.Execute();

As explained in Google Calendar API - Not Returning From Execute() C#, we currently have a bug in the latest version of Google.Apis.Auth v 1.9.3.
We already have a fix for it, in our repository (https://github.com/google/google-api-dotnet-client), so you can test it yourself with the Analytics API (https://developers.google.com/resources/api-libraries/download/analytics/v3/csharp).
A new release of the library is planned to be in the next few weeks so stay tuned - http://google-api-dotnet-client.blogspot.com/
Update (Dec 15th): New NuGet packages for 1.10.0 are available, read more about it at: http://google-api-dotnet-client.blogspot.com/2015/12/announcing-release-of-1100.html

Related

Created a user pool client using Cognito Identity Provider Client SDK for JavaScript v3, but can't fetch token using (client_credentials) grant type

Created a user pool client using Cognito Identity Provider Client SDK for JavaScript v3
npm install #aws-sdk/client-cognito-identity-provider.
The following code shows how I created the resources server and the user pool client, using the mentioned👆 SDK...
let poolName = 'UserPool';
const client =new CognitoIdentityProviderClient({
region: process.env.COGNITO_AWS_REGION
});
// create resource server
const createResourceServerCommand = new CreateResourceServerCommand({
Name: poolName,
UserPoolId: UserPool.Id,
Identifier: 'https://localhost:8080/api/v2',
Scopes: [
{
ScopeName: 'access',
ScopeDescription: 'General access to API'
}
]
});
const { ResourceServer } = await client.send(createResourceServerCommand);
// create the user pool client
const createUserPoolClientCommand = new CreateUserPoolClientCommand({
ClientName: 'Default',
UserPoolId: UserPool.Id,
ExplicitAuthFlows: ['USER_PASSWORD_AUTH'],
GenerateSecret: true,
AllowedOAuthFlows: ['client_credentials'],
SupportedIdentityProviders: ['COGNITO'],
AllowedOAuthScopes: [ 'https://localhost:8080/api/v2/access' ]
});
const { UserPoolClient } = await client.send(createUserPoolClientCommand);
...but, I can't fetch tokens using the grant type client_credentials. Therefore getting the following error.
{
"error": "invalid_grant"
}
However, if I use AWS console to navigate to the user pool > Client > Edit the hosted UI and click on the save button without making any changes...
... I am able to fetch a token using the client_credentials grant type.
Is there any setting that I might be missing in the above code that AWS console is setting? I need the following code to automate the creation of user pools.
When I switched to the old I noticed this notification
Apparently, Oauth flows are not enabled by default. Hence adding the following attribute to the CreateUserPoolClientCommandInput object AllowedOAuthFlowsUserPoolClient: true enables it. Hope this helps some newbie like me out there.

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);

Using new microsoft-graph-auth library java sdk gives unauthorized error

Permissions in azure portal I am trying to use microsoft graph auth library preview. Microsoft-graph-auth-sdk-java I am able to initialize the graphClient but unable to get data.I am getting unauthorized 401.
"code": "InvalidAuthenticationToken",
"message": "CompactToken parsing failed with error code: 80049217",
List<String> scopes = new ArrayList<String>();
scopes.add("User.Read.All");
ClientCredentialProvider authProvider = new ClientCredentialProvider(app-Id,
scopes_list,
client-Secret,
tenantId, NationalCloud.Global);
IgraphClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).logger(logger)
.buildClient();
IUserCollectionPage users = graphClient.users()
.buildRequest()
.get();
List<User> usersList = users.getCurrentPage();
for(User user : usersList) {
System.out.println(user.displayName);
}
Permissions picture Link
Permissions and code are fine. The issue must be with the library since it is in snapshot. But I guess they recently made some changes which could have fixed the issue you are facing. Try re-building the jar from the project.
For making app-only calls using client credentials you will need to pass the scope "https://graph.microsoft.com/.default" and then in the app registration portal grant admin consent for User.Read.All.

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)

OAuth 2.0 with Google Analytics API v3

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

Resources