Using C#, I am trying execute a query on Google Spanner db. I understand I can use the SpannerClient and all the current documentation explains how to execute a query quite simply, however these examples all assume default environment credentials.
I would like to execute a query against a given database but using custom credentials. So something like
var credentials = GoogleCredential.FromJson(jsonData);
SpannerClient client = new SpannerClient(connectionString, credentials)
var cmd = client.CreateSelectCommand("SELECT SingerId, AlbumId, AlbumTitle FROM Albums");
etc
I am currently unable to figure out how to do this?
Thanks
Currently this isn't as clean as we'd like it to be. You need to create a ChannelCredentials for the credentials, and provide that to the SpannerConnectionStringBuilder:
// First load the credentials, scope them, and convert to ChannelCredentials.
// You may want to move this to a separate method.
var googleCredential = GoogleCredential.FromJson(jsonData);
googleCredential = googleCredential.CreateScoped(SpannerClient.DefaultScopes);
// Use self-signed JWTs for service accounts.
// (This isn't strictly required, but reduces network usage.)
if (googleCredential.UnderlyingCredential is ServiceAccountCredential serviceCredential)
{
googleCredential = GoogleCredential.FromServiceAccountCredential(
serviceCredential.WithUseJwtAccessWithScopes(true));
}
// Note: this requires a using directive of "using Grpc.Auth;"
var channelCredentials = googleCredential.ToChannelCredentials();
// Now create a SpannerConnection with the SpannerCredentials
using var conn = new SpannerConnection(connectionString, credentials);
using var cmd = conn.CreateSelectCommand("SELECT ...");
...
We definitely hope to improve this - we have a tracking bug you might want to subscribe to so that you can simplify your code when it's fixed.
I am trying from my local web api, to retrieve secret from KeyVault using Azure.Identity lib.
but it throws Invalid Issuer. Giving below the code I am using
My current code
var client = new SecretClient(new Uri("key-vault-url"), new DefaultAzureCredential()); ==> line #1
var secret = client.GetSecret("DicomSecret").Value; ==> line #2
As soon as it parses line#2 it throws the below error.
What I have tried
I have added my Azure credential in the KeyVault thru' Add Access Policy
Tried using ManagedIdentityCredential instead of DefaultAzureCredential in line#1
Also tried using VisualStudioCredential instead of DefaultAzureCredential in line#1
I also read that I can be using EnvironmentCredential for which I need to provide AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET but I am not exactly sure how to and what to include for this - I do not have access to AAD.
Please let me know how to resolve this issue.
Since I was trying to connect to Azure from my local development environment (VS 2019) it was expecting additional credentials.
So from my dev environment (localhost) I had to use
DefaultAzureCredentialOptions VisualStudioTenantId along with SecretClient.
var tenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
DefaultAzureCredentialOptions options = new DefaultAzureCredentialOptions()
{
VisualStudioTenantId = tenantId,
SharedTokenCacheTenantId = tenantId
};
var client = new SecretClient(
new Uri(key-vault-url),
new DefaultAzureCredential(options)
);
The above helped me to execute from my local but after deploying it to Azure Ap Service the below line of code was sufficient. So I used the above code only for my local testing.
var client = new SecretClient(new Uri("key-vault-url"), new DefaultAzureCredential());
This is my code and it seems that there's no difference with yours.
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace test0430callingapi.Controllers
{
public class HelloController : Controller
{
public async Task<string> IndexAsync()
{
const string secretName = "clientsecret";
var kvUri = "https://keyvaultname.vault.azure.net/";
var a = new DefaultAzureCredential();
var client = new SecretClient(new Uri(kvUri), a);
var secret = await client.GetSecretAsync(secretName);
string secretVaule = secret.Value.Value;
return secretVaule ;
}
}
}
Then I think you may try to check the DefaultAzureCredential. When running the code in visual studio, we need to make sure that you've signed in with the user which has access permission to azure key vault by Add Access Policy in portal. Or maybe you've added the user, then you could check if has added enough permission for the user.
And if it also failed, you may try another way to access key vault by api. More details you can refer to this answer.
I am using Google.Cloud.Vision.V1, Version=2.0.0.0 and the following below code from Google Vision API specify JSON file
using Google.Apis.Auth.OAuth2;
using Google.Cloud.Vision.V1;
using Grpc.Auth;
using Grpc.Core;
var credential = GoogleCredential.FromFile("VisionProject.json");
var channel = new Grpc.Core.Channel(ImageAnnotatorClient.DefaultEndpoint.ToString(), credential.ToChannelCredentials());
var client = ImageAnnotatorClient.Create(channel);
But its shows me this error No overload for method 'ImageAnnotatorClient.Create' takes 1 arguments.
I have found similar code in documentation https://googleapis.github.io/google-cloud-dotnet/docs/Google.Cloud.Vision.V1P2Beta1/api/Google.Cloud.Vision.V1P2Beta1.ImageAnnotatorClient.html
But for some reason, it's not working( unable to see the overload)
It seems that you are using newer version of API. Docs state that now authentication is set up(when needed) via environment variable:
Otherwise, the simplest way of authenticating your API calls is to download a service account JSON file then set the GOOGLE_APPLICATION_CREDENTIALS environment variable to refer to it. The credentials will automatically be used to authenticate. See the Getting Started With Authentication guide for more details.
So you can do something like this:
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "PathTo_VisionProject.json");
var client = ImageAnnotatorClient.Create();
Or set this environment variable some other way.
While setting the environment variable is certainly a simple way of specifying which service account file to use, it's not the only one. You can use the builder to specify the path very easily:
var client = new ImageAnnotatorClientBuilder
{
CredentialsPath = "VisionProject.json"
}.Build();
Another solution if you do not have access to the JSON file directly and you want to stay close to what you previously did with the GoogleCredential and Channel creation is something like:
var credential = GoogleCredential.FromFile("VisionProject.json");
// or if you have access to the content only
// var credential = GoogleCredential.FromJson(json);
var client = await new ImageAnnotatorClientBuilder
{
Endpoint = ImageAnnotatorClient.DefaultEndpoint,
ChannelCredentials = credential.ToChannelCredentials()
}.BuildAsync();
I want to authenticate my bot by providing the bot's app id and password from a json file instead of getting the details from web.config file. I tried using connectorclient class from bot connector sdk by passing the details as an argument to it.
I am getting "AADSTS7000216: 'client_assertion', 'client_secret' or 'request' is required for the 'client_credentials' grant type." error.
Any help would be much appreciated.
The current way to store a bot's app ID and password is already in a JSON file known as a bot file. In Bot Builder V4, reading the bot file is as easy as:
botConfig = BotConfiguration.Load(botFilePath, botFileSecret);
If you want to use something like a bot file in V3 and you want to leave the credentials out of Web.config, you can create your own credential provider. You might make something like this:
using Microsoft.Bot.Connector;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace NetBot.Credentials
{
public class BotFileCredentialProvider : SimpleCredentialProvider
{
private const string BotFile = "NetBot.bot";
public BotFileCredentialProvider()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = assembly.GetManifestResourceNames().First(resource => resource.Contains(BotFile));
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
dynamic botConfig = JsonConvert.DeserializeObject(new StreamReader(stream).ReadToEnd());
IEnumerable<dynamic> services = botConfig.services;
dynamic endpoint = services.FirstOrDefault(service => service.type == "endpoint");
if (endpoint != null)
{
AppId = endpoint.appId;
Password = endpoint.appPassword;
}
}
}
}
}
This of course depends on my bot file "NetBot.bot" being an embedded resource. You'll want to modify this if your JSON is formatted differently from a bot file. To use this credential provider, you'll need to modify the BotAuthentication attribute on your messages controller:
[BotAuthentication(CredentialProviderType = typeof(BotFileCredentialProvider))]
public class MessagesController : ApiController
This of course only uses your JSON credentials to authenticate incoming messages. The Bot Builder SDK will still look for credentials in your Web.config to authenticate outgoing messages. If you want to use your JSON credentials to send messages, you can get the credentials from the claims identity:
var credentials = ((ClaimsIdentity)HttpContext.Current.User.Identity).GetCredentialsFromClaims();
var connector = new ConnectorClient(new Uri(activity.ServiceUrl), credentials);
This will work for when you construct the connector client yourself, but what if you want to send messages from a dialog context? In your Global.asax.cs file, you can insert the following code to get the SDK's connector client factory to always construct its connector clients using claims, just like how you can do it when you construct a connector client manually:
builder.Register(c => ((ClaimsIdentity)HttpContext.Current.User.Identity).GetCredentialsFromClaims())
.AsSelf()
.InstancePerLifetimeScope();
I'm trying to get some data from our google analytics instance and I'd like to use the Analytics Reporting API V4 Client Library for .NET (https://developers.google.com/api-client-library/dotnet/apis/analyticsreporting/v4) so that I can bake some of this data into an administration site we have built. I'm having trouble finding any examples of using this code and the documentation seems to be incredibly sparse. I would like to use a service account to authorize as we only need to view data associated with the analytics account which we control.
If anyone could provide some sample code or point me in the right direction to get some basic report data using the .net api, it would be greatly appreciated
Calling the Google Analytics Reporting API from C# is not particularly difficult, however all of the necessary steps do not seem to be outlined very clearly in the Google Analytics API documentation. I will try to list them all out here. While YMMV, I believe these steps to be correct as of 7/20/2016.
You can start by creating a new C# project. We'll make a console application to test called GoogleAnalyticsApiConsole. Once the project is created, we'll add a reference to the Google Analytics Reporting API V4 Client Library for .NET using the NuGet Package Manager Console (found under the Tools menu in Visual Studio 2015). Fire up the Console and issue the following command at the PM> prompt:
PM> Install-Package Google.Apis.AnalyticsReporting.v4
Installing that package will download the client libraries needed to call the Google Analytics Reporting web services along with a number of other dependencies.
In order to call the web services, you'll need to set up OAuth 2.0 access for your application. The documentation for this setup can be found here, but I will summarize below:
Login to the Google Cloud Platform Console: https://console.cloud.google.com/. Be sure to login with an account that has access to the Google Analytics accounts you are trying to query with the reporting API.
Click the Google Cloud Platform menu and select API Manager.
On the left hand side, click Credentials and then create a new project called Google Analytics API Console. Give it some time to create the new project.
After the project is created, click Credentials again if it is not already selected, and then click the OAuth Consent Screen link in the right panel. Set the Product name shown to users to Google Analytics API Console and then click Save.
Click Credentials again, and then click Create Credentials, and choose OAuth Client ID. Select Other for Application type and then enter Google Analytics API Console as the Name and click Create.
After the credential is created, you will be presented with a client ID and a client secret. You can close the dialog window.
Now, under Credentials you should see an entry under OAuth 2.0 client ids. Click the download icon to the far right of that entry to download the client_secret.json file (this file will have a much longer name). Add that file to your project at the root level once it has been downloaded and rename it to client_secret.json.
Now that the OAuth 2.0 credential has been created, we need to enable it to call the Reporting API. Select Overview and make sure Google APIs is selected in the right panel. Type in Reporting in the search box and select Analytics Reporting API V4 from the list. On the next screen, click Enable. Once this API has been enabled, you should be able to see it under the Enabled APIs list in the right panel.
Now that we've created our project and created our OAuth 2.0 credential, it is time to call the Reporting API V4. The code listed below will use the Google API and the client_secret.json file to create a Google.Apis.Auth.OAuth2.UserCredential to query the Reporting API for all sessions between the given date range for a View. The code is adapted from the Java example here.
Before executing the code, be sure to set the Build Action on the client_secret.json file to Content and the Copy to Output Directory setting to Copy if newer. There are also two variables that need to be properly set. First, in the GetCredential() method, set the loginEmailAddress value to the email address used to create the OAuth 2.0 credential. Then, in the Main method, be sure to set the ViewId in the reportRequest variable to the view that you want to query using the Reporting API. To find the ViewId, log in to Google Analytics and select the Admin tab. From there, select the view you want to query in the View dropdown on the far right and select View Settings. The View ID will be displayed under Basic Settings.
The first time the code is executed, it will bring up a web page asking if you want to allow the Google Analytics API Console to have access to the API data. Select Allow to proceed. From then on that permission will be stored in the GoogleAnalyticsApiConsole FileDataStore. If that file is deleted, then permission will need to be granted again. That file can be found in the %APPDATA%\GoogleAnalyicsApiConsole directory.
Please note that I believe this scenario will meet the needs of the OP. If this application were to be distributed to clients, then a different OAuth 2.0 scheme would most likely be necessary.
Here is the code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.AnalyticsReporting.v4;
using Google.Apis.AnalyticsReporting.v4.Data;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Util.Store;
namespace GoogleAnalyticsApiConsole
{
class Program
{
static void Main(string[] args)
{
try
{
var credential = GetCredential().Result;
using(var svc = new AnalyticsReportingService(
new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "Google Analytics API Console"
}))
{
var dateRange = new DateRange
{
StartDate = "2016-05-01",
EndDate = "2016-05-31"
};
var sessions = new Metric
{
Expression = "ga:sessions",
Alias = "Sessions"
};
var date = new Dimension { Name = "ga:date" };
var reportRequest = new ReportRequest
{
DateRanges = new List<DateRange> { dateRange },
Dimensions = new List<Dimension> { date },
Metrics = new List<Metric> { sessions },
ViewId = "<<your view id>>"
};
var getReportsRequest = new GetReportsRequest {
ReportRequests = new List<ReportRequest> { reportRequest } };
var batchRequest = svc.Reports.BatchGet(getReportsRequest);
var response = batchRequest.Execute();
foreach (var x in response.Reports.First().Data.Rows)
{
Console.WriteLine(string.Join(", ", x.Dimensions) +
" " + string.Join(", ", x.Metrics.First().Values));
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
static async Task<UserCredential> GetCredential()
{
using (var stream = new FileStream("client_secret.json",
FileMode.Open, FileAccess.Read))
{
const string loginEmailAddress = "<<your account email address>>";
return await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { AnalyticsReportingService.Scope.Analytics },
loginEmailAddress, CancellationToken.None,
new FileDataStore("GoogleAnalyticsApiConsole"));
}
}
}
}
Here are the steps updated for Sep 2019.
First, understand that there are two choices under OAuth: User credentials and Service Account credentials. User credentials are meant to be used when you do not know which Google Analytics account you will be connected to, hence the user grants your application permission. Service Account credentials are meant to be used, e.g. if you build your own dashboard for your company to display Google Analytics data.
Most of the time, if you need programmatic access to Analytics data, it is the second case.
The steps below should get you started for a simple C# example. Note that the Google web console part may vary slightly, but should be easy to find nevertheless.
Go to the Google API Console. Create a Project if prompted.
Go to Service accounts.
Create a new Service Account. You should have an account with a random-generated email address (mine is ending with xxx#xxx.iam.gserviceaccount.com)
Find the Create Key button. Choose JSON and download the file. This is your private key and your only copy. Do not lose it.
Go to your Google Analytics admin panel. Grant access to the Service Account using its email address, the same way you would grant access to other users.
The Google configuration is done. Now jump into Visual Studio.
Create a new C# Console Project.
Get the Nuget package Google.Apis.AnalyticsReporting.v4. It should also automatically download the core packages as well.
Grab the JSON file downloaded earlier, put it in the project, set its Property to Content and Copy Always.
using Google.Apis.AnalyticsReporting.v4.Data;
using System;
namespace ConsoleApplication {
class Program {
static void Main(string[] args) {
var credential = Google.Apis.Auth.OAuth2.GoogleCredential.FromFile("serviceAccount.json")
.CreateScoped(new[] { Google.Apis.AnalyticsReporting.v4.AnalyticsReportingService.Scope.AnalyticsReadonly });
using (var analytics = new Google.Apis.AnalyticsReporting.v4.AnalyticsReportingService(new Google.Apis.Services.BaseClientService.Initializer {
HttpClientInitializer = credential
})) {
var request = analytics.Reports.BatchGet(new GetReportsRequest {
ReportRequests = new[] {
new ReportRequest{
DateRanges = new[] { new DateRange{ StartDate = "2019-01-01", EndDate = "2019-01-31" }},
Dimensions = new[] { new Dimension{ Name = "ga:date" }},
Metrics = new[] { new Metric{ Expression = "ga:sessions", Alias = "Sessions"}},
ViewId = "99999999"
}
}
});
var response = request.Execute();
foreach (var row in response.Reports[0].Data.Rows) {
Console.Write(string.Join(",", row.Dimensions) + ": ");
foreach (var metric in row.Metrics) Console.WriteLine(string.Join(",", metric.Values));
}
}
Console.WriteLine("Done");
Console.ReadKey(true);
}
}
}
I had the same experience: Google's documentation is pretty in-depth but is pretty terrible at giving clear examples of how to connect with .NET.
One key thing I finally realized is that you can either connect using an OAuth2 credential or a service account credential. If you own your Analytics account, use a service account. If you're needing to connect to other users' Analytics accounts, use OAuth2.
There seem to be quite a few examples online of how to get Analytics API data using an OAuth2 credential, but I own my Analytics account and just wanted to pull data from it. I figured out how to connect to the Analytics Reporting API v4 using a ServiceAccountCredential, and I wrote an answer on a similar Stack Overflow question with all the details.
Here Is the code you actually looking for-
protected void Page_Load(object sender, EventArgs e)
{
IRestRequest request = new RestRequest("", Method.POST, DataFormat.Json);
string url = "https://analyticsreporting.googleapis.com/v4/reports:batchGet";
RestClient restClient = new RestClient();
RestRequest Tokenrequest = new RestRequest();
Tokenrequest.AddQueryParameter("client_id", "<CLIENTID>");
Tokenrequest.AddQueryParameter("client_secret", "<CLIENTSECRET>");
Tokenrequest.AddQueryParameter("grant_type", "refresh_token");
Tokenrequest.AddQueryParameter("refresh_token", "<REFRESH_TOKEN>");
restClient.BaseUrl = new System.Uri("https://oauth2.googleapis.com/token");
restClient.Post(Tokenrequest);
var responseToken = restClient.Execute(Tokenrequest);
//Response.Write(responseToken);
dynamic Tokendata = JObject.Parse(responseToken.Content);
var newToken = Tokendata.access_token.Value;
request.AddHeader("authorization", string.Concat("Bearer "+newToken));
string jsonString = "{" +
"\"reportRequests\": [{" +
"\"dateRanges\" : [{\"" +
"startDate\" :'2021-07-01' ," +
"\"endDate\" : '2021-07-07'" +
"}]," +
"\"metrics\":["+
"{\"expression\":'ga:totalEvents'},"+
"{\"expression\": 'ga:pageviews'}"+
"]," +
"\"dimensions\": ["+
"{\"name\": 'ga:eventCategory'}" +
",{" +
"\"name\": 'ga:eventAction'"+
"},"+
//"{\"name\": 'ga:deviceCategory'}"+
"]," +
"\"dimensionFilterClauses\": [{"+
"\"filters\": [{"+
"\"dimensionName\": 'ga:eventCategory',"+
"\"operator\": 'EXACT',"+
"\"expressions\": ["+
"\"Login_Form"+
"\"]}]}],"+
"\"viewId\":'<VIEWID>'" +
"}]" +
"}";
IRestClient client = new RestClient(url);
request.AddHeader("Content-Type", "application/json; CHARSET=UTF-8");
request.Resource = "";
request.AddParameter("application/json", jsonString, ParameterType.RequestBody);
var response = client.Execute(request);
dynamic jdata = JObject.Parse(response.Content);
var Row_data = jdata.reports[0].data.rows;
Response.Write(Row_data);
}
Read The Document To Get access_token through refresh_token.
https://developers.google.com/identity/protocols/oauth2/web-server#offline