i tried to retrieve data from google analytic api, and here is my class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Google.Apis.Analytics.v3;
using Google.Apis.Auth.OAuth2;
using System.Threading;
using Google.Apis.Util.Store;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Services;
namespace zirfoon.model
{
public class googleanalyze
{
public static void main(){
string[] scopes = new string[] { AnalyticsService.Scope.Analytics,AnalyticsService.Scope.AnalyticsManageUsers }; // view and manage your Google Analytics data
var keyFilePath = HttpContext.Current.Server.MapPath("/loominexMvc-f104810a4caa.p12"); // Downloaded from https://console.developers.google.com
var serviceAccountEmail = "loominexmvc#appspot.gserviceaccount.com"; // found https://console.developers.google.com
//loading the Key file
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes =scopes
}.FromCertificate(certificate));
}
}
}
when i get to line below
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes =scopes
}.FromCertificate(certificate));
visual studio debugger opens a windows to select ServiceCredential.cs but it does not exist,i changed scope but still nothing...
i have created my api account correctly and all of the information such as serviceAccountEmail and keyFilePath is correct but i still get error
Your code is a little different then what I normally use.
Authentication
string[] scopes = new string[] {AnalyticsService.Scope.Analytics}; // view and manage your Google Analytics data
var keyFilePath = #"c:\file.p12" ; // Downloaded from https://console.developers.google.com
var serviceAccountEmail = "xx#developer.gserviceaccount.com"; // found https://console.developers.google.com
//loading the Key file
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail) {
Scopes = scopes}.FromCertificate(certificate));
Create the service
var service = new AnalyticsService(new BaseClientService.Initializer() { HttpClientInitializer = credential,
ApplicationName = "Analytics API Sample",});
I would double check that your mapping to keyFilePath is correct.
Code ripped from my tutorial Google Analytics API authentcation
I found out that problem was only for debugging mode
When I ran project without debugger there was not any issue...
Related
I'm trying to get the MS example application to work for the Graph Beta Webhooks API and it's currently crashing because I've had to to modify some of the example code to remove some obsolete code and I'm not sure what to replace it with.
This is the function:
public static GraphServiceClient GetAuthenticatedClient(string userId, string redirect)
{
var graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (request) =>
{
var tokenCache = new SampleTokenCache(userId);
// Obsolete code
//var cca = new ConfidentialClientApplication(Startup.ClientId, redirect, new ClientCredential(Startup.ClientSecret), tokenCache.GetMsalCacheInstance(), null);
// New code
var cca2 = ConfidentialClientApplicationBuilder.Create(Startup.ClientId).WithClientSecret(Startup.ClientSecret).WithRedirectUri(redirect).Build();
// Question - how do I pass the tokenCache in here as the userTokenCache ?
// ERROR - With the new code this returns zero accounts presuambly because I haven't passed in a userTokenCache
var accounts = await cca2.GetAccountsAsync();
// Obsolete code
//var authResult = await cca.AcquireTokenSilentAsync(Startup.Scopes, accounts.First());
// New code
var authResult2 = await cca2.AcquireTokenSilent(Startup.Scopes, accounts.First()).ExecuteAsync();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult2.AccessToken);
}));
return graphClient;
}
If I use the ConfidentialClientApplicationBuilder then the GetAccountsAsync() returns an empty collection and I think it's because I haven't passed the tokenCache into the builder. Does anyone know how to fix this code or has anyone got the example App working ?
This is the link to the example App:
https://learn.microsoft.com/en-us/samples/microsoftgraph/aspnet-webhooks-rest-sample/microsoft-graph-aspnet-webhooks/
Thanks
Ed James
You need to login as user so that an account is added to the token cache which is available calling the tokenCache.GetMsalCacheInstance() method.
I am trying the following to get list of projects from "on prem" TFS
private static async void Method()
{
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "Username", "Password"))));
using (HttpResponseMessage response = client.GetAsync(
"http://test-test-app1:8080/tfs/boc_projects/_apis/projects?api-version=2").Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
I am using a user name and password which has admin permissions on TFS i am trying to connect.But i get unauthorized access error when i try the above.
The REST API of getting a list of team projects is:
>
http://tfsserver:8080/tfs/CollectionName/_apis/projects?api-version=1.0
Make sure you have enabled Basic Auth for your TFS:
check your IIS to see whether the Basic authentication service role is installed.
go to IIS Manager, select Team Foundation Server -- Authentication
and disable everything other than Basic Authentication. Then do the
same for the tfs node under Team Foundation Server.
restart your IIS.
Here's a simple app using the Catalog Service. It looks for a file by cycling through all Project Collections and Projects, and finds instances of the file by name. It wouldn't take much to change it for your needs.
using System;
using System.Linq;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace EpsiFinder
{
internal class Program
{
// Server URL. Yes, it's hardcoded.
public static string Url = #"http://tfs.someserver.com:8080/tfs";
private static void Main()
{
// Use this pattern search for the file that you want to find
var filePatterns = new[] { "somefile.cs" };
var configurationServerUri = new Uri(Url);
var configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(configurationServerUri);
var configurationServerNode = configurationServer.CatalogNode;
// Query the children of the configuration server node for all of the team project collection nodes
var tpcNodes = configurationServerNode.QueryChildren(
new[] { CatalogResourceTypes.ProjectCollection },
false,
CatalogQueryOptions.None);
// Changed to use the Catalog Service, which doesn't require admin access. Yay.
foreach (var tpcNode in tpcNodes)
{
Console.WriteLine("Collection: " + tpcNode.Resource.DisplayName + " - " + tpcNode.Resource.Description);
// Get the ServiceDefinition for the team project collection from the resource.
var tpcServiceDefinition = tpcNode.Resource.ServiceReferences["Location"];
var configLocationService = configurationServer.GetService<ILocationService>();
var newUrl = new Uri(configLocationService.LocationForCurrentConnection(tpcServiceDefinition));
// Connect to the team project collection
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(newUrl);
// This is where we can do stuff with the team project collection object
// Get the Version Control instance
var versionControl = tfs.GetService<VersionControlServer>();
// Select the branches that match our criteria
var teamBranches = versionControl.QueryRootBranchObjects(RecursionType.Full)
.Where(s => !s.Properties.RootItem.IsDeleted)
.Select(s => s.Properties.RootItem.Item)
.ToList();
// Match the file in the branches, spit out the ones that match
foreach (var item in from teamBranch in teamBranches
from filePattern in filePatterns
from item in
versionControl.GetItems(teamBranch + "/" + filePattern, RecursionType.Full)
.Items
select item)
Console.WriteLine(item.ServerItem);
}
}
}
}
I am working on a app using gmail api.
I want to perform archive functionality.
I had gone through the api https://developers.google.com/gmail/api but unable to find any desired solutions.
Can anyone suggest me any solution for the same.
Thanks in Advance.
A archived message is just a message that lies in the All Mail (which isn't an actual label). You can achieve this by removing the INBOX-label on the message (or any other label you have added to it), which can be achieved with modify.
C# Code for Gmail APIs Archive email by using OAuth 2.0 service.
class ReadAllMails
{
static string[] Scopes = { GmailService.Scope.MailGoogleCom };
static string ApplicationName = "Gmail API .NET Quickstart";
static void Main(string[] args)
{
UserCredential credential;
using (var stream =
new FileStream("credentials_dev.json", FileMode.Open, FileAccess.Read))
{
string credPath = "token_MailGoogleCom.json";
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
}
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
List<string> lableIds = new List<string>();
lableIds.Add("INBOX");
ModifyMessageRequest mods = new ModifyMessageRequest();
mods.RemoveLabelIds= lableIds;
service.Users.Messages.Modify(mods, "me", emailId).Execute();
//emailId that you want to archive
}
}
I'm trying to get in memory hosting working for integration testing our web api project, but have hit an issue with authentication when using it. I have recreated this on a basic Web Api project using the default Web Api template and the values controller it creates.
We are using Autofac so have included this in the test too. We are also using windows authentication for the web api, but for the purposes of the test this is not important.
The issue is that the "server" in the test always returns "Authorization has been denied for this request."
So what is the best way to authorize with the in memory server? I've commented out some code from another stackoverflow question but that also didn't seem to work.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web.Http;
using Autofac;
using Autofac.Integration.WebApi;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WebApiTesting.Controllers;
namespace WebApiTesting.Tests.Controllers
{
[TestClass]
public class ValuesControllerTest
{
private const string URL = "http://test.testing.com/";
private const string Username = "user";
private const string Password = "supersecret";
[TestMethod]
public void InMemoryHosting()
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional});
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
var server = new HttpServer(config);
var builder = new ContainerBuilder();
// Register API controllers using assembly scanning.
builder.RegisterApiControllers(typeof(ValuesController).Assembly);
var container = builder.Build();
server.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
var client = new HttpClient(server);
using (var request = CreateRequest("api/values", "application/json", HttpMethod.Get))
{
//Act
using (HttpResponseMessage response = client.SendAsync(request).Result)
{
// Assert
Assert.IsNotNull(response.Content);
Assert.AreEqual("application/json", response.Content.Headers.ContentType.MediaType);
var content = response.Content.ReadAsStringAsync().Result;
Assert.AreNotEqual("{\"Message\":\"Authorization has been denied for this request.\"}", content);
}
}
}
private HttpRequestMessage CreateRequest(string url, string mthv, HttpMethod method)
{
var request = new HttpRequestMessage { RequestUri = new Uri(URL + url) };
/*byte[] toEncodeAsBytes = Encoding.UTF8.GetBytes(string.Format("{0}:{1}", Username, Password));
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(toEncodeAsBytes));*/
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(mthv));
request.Method = method;
return request;
}
}
}
Just to document what worked in the end, I added the following line to my CreateRequest Method
Thread.CurrentPrincipal = new ClientRolePrincipal(new HttpListenerBasicIdentity(Username, Password));
I'm not really sure if this is the best way to handle it, but it does work at least.
I'm a hobby developer and I am fiddlng around with asp.net MVC and was trying to just get the basic Oauth to work via Twitter.
All I did was put a controller named Twitter with this code:
(it's from an online example for webforms but i slightly modified it and put it into 2 action methods, index and callback.. is this right way to do it ?)
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using OAuthLibrary;
namespace mvcTwit.Controllers
{
public class TwitterController : Controller
{
private const string AccessUrl = "http://twitter.com/oauth/access_token";
private const string AuthorizeUrl = "http://twitter.com/oauth/authorize?oauth_token={0}";
private const string RequestUrl = "http://twitter.com/oauth/request_token";
//
// GET: /Twitter/
public ActionResult Index()
{
// add these to web.config
var consumerKey = ConfigurationManager.AppSettings["consumerKey"];
var consumerSecret = ConfigurationManager.AppSettings["consumerSecret"];
// look for an access token in the callback
var requestToken = Request.QueryString["oauth_token"];
if (requestToken == null)
{
requestToken = OAuth.GetRequestToken(RequestUrl,
consumerKey,
consumerSecret);
var collection = HttpUtility.ParseQueryString(requestToken);
var authorizeUrl = String.Format(AuthorizeUrl,
collection[0]);
Response.Redirect(authorizeUrl);
}
return View();
}
public ActionResult Callback(string oauth_token)
{
var consumerKey = ConfigurationManager.AppSettings["consumerKey"];
var consumerSecret = ConfigurationManager.AppSettings["consumerSecret"];
//var requestToken = Request.QueryString["oauth_token"];
var requestToken = oauth_token;
// oauth is complete and callback is returning
// the possibly authorized request token
var collection = HttpUtility.ParseQueryString(requestToken);
// obtain access token
var accessToken = OAuth.GetAccessToken(AccessUrl,
consumerKey,
consumerSecret,
collection[0],
collection[1]);
collection = HttpUtility.ParseQueryString(accessToken);
// make a Twitter request with the access token and secret
var url = "http://twitter.com/account/verify_credentials.xml";
var verify = OAuth.GetProtectedResource(url,
"GET",
consumerKey,
consumerSecret,
collection[0],
collection[1]);
ViewData["oauth_token"] = verify;
return View();
}
}
}
When i go to mysite.com/Twitter, it does its thing and takes me to twitter.com/oauth/authorize?oauth_token=(long string here)
Then after i fill in my u/n and p/w, it takes me back to my site:
mysite.com/Twitter/callback?oauth_token=(long string)
but the error on the page is:
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
My question is, is the signature of the Callback action correct because it expects a string back from twitter. And obviously I need to add a route in my global.asax file. What would that route look like?.. I have tried everything and i can't get it to work. Is the root of my issue or am i making a programming mistake..lol
Don't be hard on me, i'm no expert, but just learning as i go.
And, I'm testing this on a website, not localhost.
Thank You.
p.s. I have spent way to long on this and am looking for help as a last resort, so thanks for your kindness.
Looks like var collection = HttpUtility.ParseQueryString(requestToken); is not returning you two results as you expect;
var accessToken = OAuth.GetAccessToken(
AccessUrl, consumerKey, consumerSecret,
collection[0], collection[1]); <<-- this line is your problem?
I think you need to split the collection[0] into the two Oauth token parts.