Google BigQuery Service Account Credentials using JSON file in C# application - google-bigquery

While Creating Service Account for Google BigQuery, There are two key file type. 1. P12 Key File 2. JSON Key File.
I can able to connect Google BigQuery with Service Account Credentials using P12 Key File by using following code.
String serviceAccountEmail = "XXXX#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"FileName.p12", "Secret Key", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { BigqueryService.Scope.Bigquery, BigqueryService.Scope.BigqueryInsertdata, BigqueryService.Scope.CloudPlatform, BigqueryService.Scope.DevstorageFullControl }
}.FromCertificate(certificate));
BigqueryService Service = new BigqueryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "PROJECT NAME"
});
Now i am trying to connect Service Account Credentials using JSON file type, but i could not get the proper syntax for creating.
How can we connect Google BigQuery with Service Account Credentials using JSON File?
Thanks,

I got the link, Which indicates Service Account Authentication using JSON file in C# application is not yet added in Google BigQuery API, So i would like to close the question.
https://github.com/google/google-api-dotnet-client/issues/533

It is now possible (I used v 1.13.1.0 of Google APIs).
GoogleCredential credential;
using (Stream stream = new FileStream(#"C:\mykey.json", FileMode.Open, FileAccess.Read, FileShare.Read))
{
credential = GoogleCredential.FromStream(stream);
}
string[] scopes = new string[] {
BigqueryService.Scope.Bigquery,
BigqueryService.Scope.CloudPlatform,
};
credential = credential.CreateScoped(scopes);
BaseClientService.Initializer initializer = new BaseClientService.Initializer()
{
HttpClientInitializer = (IConfigurableHttpClientInitializer)credential,
ApplicationName = "My Application",
GZipEnabled = true,
};
BigqueryService service = new BigqueryService(initializer);

Related

How to use UserCredential in ASP.NET Core MVC web application?

I have a small issue creating a user credential (oauth 2.0) for implementing youtube-data api (video upload) in my .NET Core app.
In a console app I download the credential file from google and use it like that:
UserCredential credential;
using (var stream = new FileStream(#"C:\Users\Gaby\source\repos\Youtube Api\client.txt", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YouTubeService.Scope.YoutubeUpload },
"user", CancellationToken.None);
}
However I tried to use the same code in an ASP.NET Core MVC app, but I get this error:
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. [401]
And to implement this credential I use this code sample:
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
});
Just use the same code in the Asp.Net core app It works!

Google API - Authentication setup and .NET client

I'm trying to achieve two things from my C# client application using Google API.
List all users of my google directory
Get metadata of all emails for each user
It appears, however, that my service account configuration is giving me issues. This is what I have done.
Created project in console.cloud.google.com
Enabled Admin SDK and Gmail API from API's and Services
Created Service Account with Domain-Wide delegation and obtained credentials.json file.
4. On admin.google.com I went to Security / API Controls and manage Domain-wide delegation. From here I added new API Client from my Service Account client id and assigned the following scopes:
https://www.googleapis.com/auth/gmail.settings.basic
https://www.googleapis.com/auth/gmail.settings.sharing
https://www.googleapis.com/auth/admin.directory.user.readonly
Finally, when I want to try to retrieve users list I get error: Expected OAuth 2 access token, login cookie or other valid authentication credential
static void Main(string[] args)
{
using (var stream =
new FileStream("..\\..\\..\\credentials.json", FileMode.Open, FileAccess.Read))
{
var credential = GoogleCredential.FromFile("..\\..\\..\\credentials.json");
var dirservice = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "testbuildingnomiproductname",
});
var listReq = dirservice.Users.List();
Users allUsers = listReq.Execute();
int counter = 0;
foreach (User myUser in allUsers.UsersValue)
{
Console.WriteLine("*" + myUser.PrimaryEmail);
counter++;
}
Console.WriteLine(counter);
Console.ReadKey();
}
}

Call Azure API from WebJob/ Shared code between WebJob and web api

I have a web api in an ASE and an associated web job. I am trying to call this web api from the web job but it always fails with winhttpexception: a security error has occurred. I have put in all the tls related settings but still getting the error.
Any suggestions on the error?
Also is there a way to share code between WebJob and web api?
I was able to resolve the issue by setting the below in my code.This resolved the Security Error.
using(var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (sender,certificate,chain,sslPolicyErrors) => true
})
You could create a console app and publish it as Azure WebJobs. For username and password you could click Get Publish Profile in your Azure webapp overview to get them.
Then you could use the following code in Console App to call your Azure Webapi.
string userName = "$xxxxxx";
string userPassword = "xxxxxxxxxxxxx";
string webAppName = "xxxxxx";
var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{userName}:{userPassword}"));
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Basic " + base64Auth);
var baseUrl = new Uri($"https://{webAppName}.azurewebsites.net/api/values");
var result = client.GetAsync(baseUrl).Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsStringAsync();
readTask.Wait();
var value = readTask.Result;
Console.WriteLine(value.ToString());
}
}
Console.WriteLine("run successfully");
Output as below:

How to fetch email in web api 2 which is secured by WAAD

I am using MVC 5 client which is secured by "UseOpenIdConnectAuthentication" and getting all user details in Claims object, this client is calling WAAD secured Web Api by "Bearer" authentication token.
I need to fetch username or email in the web api. I tried different options but nothing worked.
I am getting null in Identity.Name, other properties I am getting like nameidentifier, objectidentifier, tenanted etc.
Please advise.
Thanks
Below code I am using for access token in Web Client.
string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
ClientCredential clientcred = new ClientCredential(Startup.clientId, Startup.appKey);
AuthenticationContext authenticationContext = new AuthenticationContext(Startup.aadInstance + Startup.tenantId, new ADALTokenCache(signedInUserID));
AuthenticationResult authenticationResult = authenticationContext.AcquireToken(apiResourceId, clientcred);
return authenticationResult.AccessToken;
Start up Code
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = Authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
// If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
AuthorizationCodeReceived = (context) =>
{
var code = context.Code;
ClientCredential credential = new ClientCredential(clientId, appKey);
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
AuthenticationContext authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID));
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
return Task.FromResult(0);
}
Below are the Token Details:
You can get the upn of current user by :
var upn = ClaimsPrincipal.Current.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn").Value;
Other way is getting user's basic information using Microsoft Graph api , please refer to On-Behalf-Of scenario .The OAuth 2.0 On-Behalf-Of flow serves the use case where an application invokes a service/web API, which in turn needs to call another service/web API. Please refer to protocol explanation and code sample .
Update :
Looking into your codes , you are using client credential flow to acquire token for your web api :
AuthenticationResult authenticationResult = authenticationContext.AcquireToken(apiResourceId, clientcred);
The OAuth 2.0 Client Credentials Grant Flow permits a web service (confidential client) to use its own credentials instead of impersonating a user, to authenticate when calling another web service. That's why you can't get upn information which associated with a user .
You can use authorization code flow with user's identity , Please refer to code sample :
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID));
ClientCredential credential = new ClientCredential(clientId, appKey);
result = await authContext.AcquireTokenSilentAsync(todoListResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));

Office365 authentication without login redirection

I'm trying to load data from Office365 email without need for user interaction. I've created Azure App and I have Client ID and Client secret.
I also have user information (email + password).
I need to call Office365 API to download emails from mailbox. But I need application to download them in background without user interaction (redirecting to MS/Office365 login page) to get authenticated/logged into mailbox.
Is there any way how to do this only through Office API, without need of redirection?
Thanks for any info.
Yes, you are able to create a daemon service app using the Client Credential flow to authenticate the app.
Here is a code sample to retrieve the mails using Microsoft Graph SDK with this flow:
string clientId = "";
string clientsecret = "";
string tenant = "";
string resourceURL = "https://graph.microsoft.com";
string authority = "https://login.microsoftonline.com/" + tenant + "/oauth2/token";
string userMail = "user1#yourdomain.onmicrosoft.com";
var credential = new ClientCredential(clientId, clientsecret);
AuthenticationContext authContext =new AuthenticationContext(authority);
var authResult = await authContext.AcquireTokenAsync(resourceURL, credential);
var graphserviceClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
(requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authResult.AccessToken);
return Task.FromResult(0);
}));
var items = await graphserviceClient.Users[userMail].Messages.Request().OrderBy("receivedDateTime desc").GetAsync();
foreach (var item in items)
{
Console.WriteLine(item.Subject);
}
And we need to register the app on the Azure AD portal and grant the app Mail.Read scope like figure below:
Refer to here for more detail about calling Microsoft Graph in a service or daemon app