I've followed the documentation steps and everything went smooth until step 5.
After successful authorization I've tried to access account data, like in step 5
var api = new API(ConsumerKey, ConsumerSecret);
api.OAuthToken = "My OAuthToken"; // That I've received on step 4
Account account = api.getAccount();
and I've got 401 exception on api.getAccount();
Please tell me what am I missing? What am I doing wrong?
Thanks
I've found a solution. In order someone else has the same issue, here is fully functional code example
public class AWeber
{
public void Authorize()
{
var Session = HttpContext.Current.Session;
var api = new API(AppSettings.AWebberConsumerKey, AppSettings.AWebberConsumerSecret);
api.CallbackUrl = "http://localhost:61006/test.aspx";
api.get_request_token();
Session["OAuthToken"] = api.OAuthToken;
Session["OAuthTokenSecret"] = api.OAuthTokenSecret;
api.authorize();
}
public void InitAccessToken(string OAuthVerifier)
{
var Session = HttpContext.Current.Session;
var api = new API(AppSettings.AWebberConsumerKey, AppSettings.AWebberConsumerSecret);
api.OAuthToken = (string)Session["OAuthToken"];
api.OAuthTokenSecret = (string)Session["OAuthTokenSecret"];
api.OAuthVerifier = OAuthVerifier;
// These two are final token that are needed
Session["OAuthToken"] = api.get_access_token();
Session["OAuthTokenSecret"] = api.adapter.OAuthTokenSecret;
}
public void GetData()
{
var Session = HttpContext.Current.Session;
var api = new API(AppSettings.AWebberConsumerKey, AppSettings.AWebberConsumerSecret);
api.adapter.OAuthToken = (string)Session["OAuthToken"];
api.adapter.OAuthTokenSecret = (string)Session["OAuthTokenSecret"];
Account account = api.getAccount();
}
}
Related
Trying to get all the categories from Ebay to shove into the database. I've tried increasing the timeout value of the underlying api context, but I still get a timeout after about two minutes - what else do I need to do?
var c = new eBay.Service.Call.GetCategoriesCall(this.apiContext);
c.CategorySiteID = ((int)siteId).ToString(); // siteId is an eBay SiteCode enum value
var version = c.GetCategoriesVersion();
c.DetailLevelList = new DetailLevelCodeTypeCollection();
c.DetailLevelList.Add(DetailLevelCodeType.ReturnAll);
c.ViewAllNodes = !onlyLeafCategories;
c.Timeout = 1000*60*20;
c.GetCategories(); // this causes a connection closed / timeout
Try this code, it works for me :
// get all categories from eBay
ApiContext context = GetApiContext();
GetCategoriesCall apiCall = new GetCategoriesCall(context)
{
EnableCompression = true,
ViewAllNodes = true
};
apiCall.DetailLevelList.Add(DetailLevelCodeType.ReturnAll);
apiCall.GetCategories();
public static ApiContext GetApiContext()
{
//apiContext is a singleton,
//to avoid duplicate configuration reading
if (apiContext != null)
{
return apiContext;
}
else
{
apiContext = new ApiContext();
//set Api Server Url
apiContext.SoapApiServerUrl = "https://api.ebay.com/wsapi";
//set Api Token to access eBay Api Server
ApiCredential apiCredential = new ApiCredential();
apiCredential.eBayToken ="YOUR_TOKEN";
apiContext.ApiCredential = apiCredential;
//set eBay Site target to US
apiContext.Site = eBay.Service.Core.Soap.SiteCodeType.US;
return apiContext;
}
}
I have a generic handler written in C# - this is called as part of an OAuth2 process to validate users via Google.
Once the correct user is identified I need to set a cookie so the rest of the site can then identify the user.
The trouble is in order to set session variables the handler needs to implement IRequiresSessionState - when I do that - then the OAuth 2 process fails with the following error.
Unexpected OAuth authorization response received with callback and client state that does not match an expected value
So I can implement OAuth or write a session variable but cannot do both. I could get OAuth to call the first page but then the code can be seen in the URL (which I would rather not do - as it gives clues for any nefarious person to break security ). I could get a page to call the handler, return JSON to identify the user and have the page itself set the session variable, then go to the first page - but this page would have no content, as well as requiring two hops - so how can you have an HTML page which is essentially empty, or set the session without IRequiresSessionState breaking the session.
The code for the OAuth handler is shown below.
public void ProcessRequest(HttpContext context)
{
NetworkParameters networkParameters = null;
NetworkParameter networkParameter = null;
WebServerClient consumer = null;
AuthorizationServerDescription server = null;
IAuthorizationState grantedAccess = null;
LoginResult loginResult = null;
String code = String.Empty;
String result = String.Empty;
String consumerSecret = String.Empty;
String consumerKey = String.Empty;
String securityCookieVal = String.Empty;
Uri tokenEndpoint = null;
Uri authorizationEndpoint = null;
Profile profile = null;
Profile profile2 = null;
Profiles profiles = null;
NetworkAuthorizations authorizations = null;
NetworkAuthorization na = null;
try
{
loginResult = new LoginResult();
tokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token");
authorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=auto");
// retrieve network parameters
networkParameters = new NetworkParameters(Properties.Settings.Default.DatabaseConnection);
authorizations = new NetworkAuthorizations(Properties.Settings.Default.DatabaseConnection);
networkParameter = networkParameters.Select("GOOGLE");
code = context.Request["code"];
consumerKey = networkParameter.ClientId;
consumerSecret = networkParameter.ClientSecret;
// set up request
server = new AuthorizationServerDescription();
server.AuthorizationEndpoint = authorizationEndpoint;
server.TokenEndpoint = tokenEndpoint;
server.ProtocolVersion = ProtocolVersion.V20;
// initialise webserver client
consumer = new WebServerClient(server, consumerKey, consumerSecret);
consumer.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(consumerSecret);
// retrieve access
grantedAccess = consumer.ProcessUserAuthorization();
profile = GoogleServices.GetProfile(grantedAccess.AccessToken);
profiles = new Profiles(Properties.Settings.Default.DatabaseConnection);
profile2 = profiles.SelectByNetworkId(profile.Network, profile.NetworkId);
if (profile2 == null)
{
na = new NetworkAuthorization()
{
Id = Guid.NewGuid().ToString(),
AccessToken = grantedAccess.AccessToken,
ExpirationDate = (DateTime)grantedAccess.AccessTokenExpirationUtc,
IssueDate = (DateTime)grantedAccess.AccessTokenIssueDateUtc,
RefreshToken = grantedAccess.RefreshToken,
Network = profile.Network,
NetworkId = profile.NetworkId
};
authorizations.Insert(na);
profiles.Insert(profile);
}
loginResult.UserId = profile.NetworkId;
}
catch (System.Exception e)
{
loginResult.Status.Status = "ERROR";
loginResult.Status.Message = e.Message;
}
finally
{
context.Response.ContentType = "application/json";
context.Response.Write(JsonConvert.SerializeObject(loginResult));
}
}
Not really an answer - but I got around this by passing a randomly generated id to the first page of the website, and storing it against the user - cookie was set when the first page was called.
Not really secure sending such information in the query string but will suffice in what is a prototype - eventual plan is to use Node.js where this will not be an issue.
I am using the NuGet Yammer API and I am trying to simply authenticate and display the token as a test.
Unfortunately I can't seem to get it working. I am new to this but there is no documentation on the NuGet Yammer API and it will be a console application. All the examples and documentation on the Yammer developers page show doing this from a web based appication.
My code so far:
static void Main(string[] args)
{
var myConfig = new ClientConfigurationContainer
{
ClientCode = null,
ClientId = "CODEHERE",
ClientSecret = "CODEHERE"
};
var myYammer = new YammerClient(myConfig);
var test = myYammer.GetToken();
Console.WriteLine("Token" + test);
Console.ReadLine();
}
It's an OAuth authentication, you must interact with Yammer OAuth webpage to obtain a token.
You should look in the asp.net mvc example in sources on Github.
In the HomeController.cs :
[HttpPost]
public ActionResult Index(IndexViewModel model)
{
if (ModelState.IsValid)
{
var myConfig = new ClientConfigurationContainer
{
ClientCode = null,
ClientId = model.ClientId,
ClientSecret = model.ClientSecret,
RedirectUri = Request.Url.AbsoluteUri + Url.Action("AuthCode")
};
var myYammer = new YammerClient(myConfig);
// Obtain the URL of Yammer Authorisation Page
var url = myYammer.GetLoginLinkUri();
this.TempData["YammerConfig"] = myConfig;
// Jump to the url page
return Redirect(url);
}
return View(model);
}
And Yammer redirect you here:
public ActionResult AuthCode(String code)
{
if (!String.IsNullOrWhiteSpace(code))
{
var myConfig = this.TempData["YammerConfig"] as ClientConfigurationContainer;
myConfig.ClientCode = code;
var myYammer = new YammerClient(myConfig);
// var yammerToken = myYammer.GetToken();
// var l = myYammer.GetUsers();
// var t= myYammer.GetImpersonateTokens();
// var i = myYammer.SendInvitation("test#test.fr");
// var m = myYammer.PostMessage("A test from here", 0, "Event");
return View(myYammer.GetUserInfo());
}
return null;
}
The person who wrote the API also wrote an article on how to use it, which is here:
http://fullsaas.blogspot.fr/2013/05/a-simple-net-wrapper-of-yammer-api.html
This may also be useful:
https://blogs.technet.com/b/speschka/archive/2013/10/05/using-the-yammer-api-in-a-net-client-application.aspx
I'm writing a program to allow a user to upload files to their Google Drive account. I have the upload part working and am using OAuth2. The issue I'm currently having is getting a list of folders from the users Drive account.
I found some code that is supposed to do this using the .setUserCredentials method, but it doesn't work:
DocumentsService service1 = new DocumentsService("project");
service1.setUserCredentials("user","pass");
FolderQuery query1 = new FolderQuery();
// Make a request to the API and get all documents.
DocumentsFeed feed = service1.Query(query1);
// Iterate through all of the documents returned
foreach (DocumentEntry entry in feed.Entries)
{
var blech = entry.Title.Text;
}
Nothing is returned. Ideally, I want to use OAuth2 to do this. I've been trying with the following code, trying to set the authentication token, but I always get denied access:
String CLIENT_ID = "clientid";
String CLIENT_SECRET = "secretid";
var docprovider = new NativeApplicationClient(GoogleAuthenticationServer.Description, CLIENT_ID, CLIENT_SECRET);
var docstate = GetDocAuthentication(docprovider);
DocumentsService service1 = new DocumentsService("project");
service1.SetAuthenticationToken(docstate.RefreshToken);
FolderQuery query1 = new FolderQuery();
DocumentsFeed feed = service1.Query(query1); //get error here
// Iterate through all of the documents returned
foreach (DocumentEntry entry in feed.Entries)
{
// Print the title of this document to the screen
var blech = entry.Title.Text;
}
..
private static IAuthorizationState GetDocAuthentication(NativeApplicationClient client)
{
const string STORAGE = "storagestring";
const string KEY = "keystring";
string scope = "https://docs.google.com/feeds/default/private/full/-/folder";
// Check if there is a cached refresh token available.
IAuthorizationState state = AuthorizationMgr.GetCachedRefreshToken(STORAGE, KEY);
if (state != null)
{
try
{
client.RefreshToken(state);
return state; // Yes - we are done.
}
catch (DotNetOpenAuth.Messaging.ProtocolException ex)
{
}
}
// Retrieve the authorization from the user.
state = AuthorizationMgr.RequestNativeAuthorization(client, scope);
AuthorizationMgr.SetCachedRefreshToken(STORAGE, KEY, state);
return state;
}
Specifically, I get "Execution of request failed: https://docs.google.com/feeds/default/private/full/-/folder - The remote server returned an error: (401) Unauthorized".
I've also tried:
var docauth = new OAuth2Authenticator<NativeApplicationClient>(docprovider, GetDocAuthentication);
DocumentsService service1 = new DocumentsService("project");
service1.SetAuthenticationToken(docauth.State.AccessToken);
but "State" is always null, so I get a null object error. What am I doing wrong and how is this done?
You should use the Drive SDK, not the Documents List API, which allows you to list folders. You can use "root" as a folderId if you want to list the root directory.
I actually implemented the v3 version of the GDrive SDK for .NET and needed to search for folders as well.
I prefer requesting uniquely all folders instead of getting all files and then performing a LinQ query to keep just the folders.
This is my implementation:
private async Task<bool> FolderExistsAsync(string folderName)
{
var response = await GetAllFoldersAsync();
return response.Files
.Where(x => x.Name.ToLower() == folderName.ToLower())
.Any();
}
private async Task<Google.Apis.Drive.v3.Data.FileList> GetAllFoldersAsync()
{
var request = _service.Files.List();
request.Q = "mimeType = 'application/vnd.google-apps.folder'";
var response = await request.ExecuteAsync();
return response;
}
You could request the name on the Q this way as well:
request.Q = $"mimeType = 'application/vnd.google-apps.folder' and name = '{folderName}'";
Which would lead and simplify things to (obviating null checking):
private async Task<bool> FolderExistsAsync(string folderName)
{
var response = await GetDesiredFolder(folderName);
return response.Files.Any();
}
private async Task<FileList> GetDesiredFolder(string folderName)
{
var request = _service.Files.List();
request.Q = $"mimeType = 'application/vnd.google-apps.folder' and name = '{folderName}'";
var response = await request.ExecuteAsync();
return response;
}
private IEnumerable<DocumentEntry> GetFolders(string id) {
if (IsLogged) {
var query = new FolderQuery(id)
{
ShowFolders = true
};
var feed = GoogleDocumentsService.Query(query);
return feed.Entries.Cast<DocumentEntry>().Where(x => x.IsFolder).OrderBy(x => x.Title.Text);
}
return null;
}
...
var rootFolders = GetFolders("root");
if (rootFolders != null){
foreach(var folder in rootFolders){
var subFolders = GetFolders(folder.ResourceId);
...
}
}
where GoogleDocumentsService is a instance of DocumentsService and IsLogged is a success logged flag.
I got this way to get list of folders from google drive
FilesResource.ListRequest filelist= service.Files.List();
filelist.Execute().Items.ToList().Where(x => x.MimeType == "application/vnd.google-apps.folder").ToList()
Working Platform: ASP.NET 4.0 C# ( Framework Agnostic )
Google GData is my dependency
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Documents;
I have two pages Auth and List.
Auth redirects to Google Server like this
public ActionResult Auth()
{
var target = Request.Url.ToString().ToLowerInvariant().Replace("auth", "list");
var scope = "https://docs.google.com/feeds/";
bool secure = false, session = true;
var authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
return new RedirectResult(authSubUrl);
}
Now it reaches the List Page if Authentication is successful.
public ActionResult List()
{
if (Request.QueryString["token"] != null)
{
String singleUseToken = Request.QueryString["token"];
string consumerKey = "www.blahblah.net";
string consumerSecret = "my_key";
string sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null).ToString();
var authFactory = new GOAuthRequestFactory("writely", "qwd-asd-01");
authFactory.Token = sessionToken;
authFactory.ConsumerKey = consumerKey;
authFactory.ConsumerSecret = consumerSecret;
//authFactory.TokenSecret = "";
try
{
var service = new DocumentsService(authFactory.ApplicationName) { RequestFactory = authFactory };
var query = new DocumentsListQuery();
query.Title = "project";
var feed = service.Query(query);
var result = feed.Entries.ToList().ConvertAll(a => a.Title.Text);
return View(result);
}
catch (GDataRequestException gdre)
{
throw;
}
}
}
This fails at the line var feed = service.Query(query); with the error
Execution of request failed: https://docs.google.com/feeds/default/private/full?title=project
The HttpStatusCode recieved on the catch block is HttpStatusCode.Unauthorized
What is wrong with this code? Do I need to get TokenSecret? If so how?
You need to request a token from Google and use it to intialize your DocumentsService instance.
Here's an example using Google's ContactsService. It should be the same for the DocumentsService.
Service service = new ContactsService("My Contacts Application");
service.setUserCredentials("your_email_address_here#gmail.com", "yourpassword");
var token = service.QueryClientLoginToken();
service.SetAuthenticationToken(token);
But as you mentioned, you are using AuthSub. I jumped the gun a bit too fast.
I see that you are requesting a session token. According to the documentation of the API you must use the session token to authenticate requests to the service by placing the token in the Authorization header. After you've set the session token, you can use the Google Data APIs client library.
Here's a complete example (by Google) on how to use AuthSub with the .NET client library:
http://code.google.com/intl/nl-NL/apis/gdata/articles/authsub_dotnet.html
Let me include a shortened example:
GAuthSubRequestFactory authFactory =
new GAuthSubRequestFactory("cl", "TesterApp");
authFactory.Token = (String) Session["token"];
CalendarService service = new CalendarService(authFactory.ApplicationName);
service.RequestFactory = authFactory;
EventQuery query = new EventQuery();
query.Uri = new Uri("http://www.google.com/calendar/feeds/default/private/full");
EventFeed calFeed = service.Query(query);
foreach (Google.GData.Calendar.EventEntry entry in calFeed.Entries)
{
//...
}
And if I see correctly your example code pretty follows the same steps, except that you set the ConsumerKey and ConsumerSecret for the AuthFactory which is not done in the example by Google.
Used the 3-legged OAuth in the Google Data Protocol Client Libraries
Sample Code
string CONSUMER_KEY = "www.bherila.net";
string CONSUMER_SECRET = "RpKF7ykWt8C6At74TR4_wyIb";
string APPLICATION_NAME = "bwh-wssearch-01";
string SCOPE = "https://docs.google.com/feeds/";
public ActionResult Auth()
{
string callbackURL = String.Format("{0}{1}", Request.Url.ToString(), "List");
OAuthParameters parameters = new OAuthParameters()
{
ConsumerKey = CONSUMER_KEY,
ConsumerSecret = CONSUMER_SECRET,
Scope = SCOPE,
Callback = callbackURL,
SignatureMethod = "HMAC-SHA1"
};
OAuthUtil.GetUnauthorizedRequestToken(parameters);
string authorizationUrl = OAuthUtil.CreateUserAuthorizationUrl(parameters);
Session["parameters"] = parameters;
ViewBag.AuthUrl = authorizationUrl;
return View();
}
public ActionResult List()
{
if (Session["parameters"] != null)
{
OAuthParameters parameters = Session["parameters"] as OAuthParameters;
OAuthUtil.UpdateOAuthParametersFromCallback(Request.Url.Query, parameters);
try
{
OAuthUtil.GetAccessToken(parameters);
GOAuthRequestFactory authFactory = new GOAuthRequestFactory("writely", APPLICATION_NAME, parameters);
var service = new DocumentsService(authFactory.ApplicationName);
service.RequestFactory = authFactory;
var query = new DocumentsListQuery();
//query.Title = "recipe";
var feed = service.Query(query);
var docs = new List<string>();
foreach (DocumentEntry entry in feed.Entries)
{
docs.Add(entry.Title.Text);
}
//var result = feed.Entries.ToList().ConvertAll(a => a.Title.Text);
return View(docs);
}
catch (GDataRequestException gdre)
{
HttpWebResponse response = (HttpWebResponse)gdre.Response;
//bad auth token, clear session and refresh the page
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
Session.Clear();
Response.Write(gdre.Message);
}
else
{
Response.Write("Error processing request: " + gdre.ToString());
}
throw;
}
}
else
{
return RedirectToAction("Index");
}
}
This 2-legged sample never worked for me for google docs.