I am using oauth to get acces to google contacts from a desktop application. I have followed the instruction from google here: http://code.google.com/intl/iw-IL/apis/gdata/docs/auth/oauth.html#Examples but I am having problems
here is the code:
OAuthParameters parameters = new OAuthParameters()
{
ConsumerKey = CONSUMER_KEY,
ConsumerSecret = CONSUMER_SECRET,
Scope = SCOPE,
Callback = "http://localhost:10101/callback.htm.txt",
SignatureMethod = "HMAC-SHA1"
};
OAuthUtil.GetUnauthorizedRequestToken(parameters);
string authorizationUrl = OAuthUtil.CreateUserAuthorizationUrl(parameters);
Console.WriteLine(authorizationUrl);
var win = new GoogleAuthenticationWindow(authorizationUrl,parameters);
win.ShowDialog();
OAuthUtil.GetAccessToken(parameters);
inside the window I have the following:
private void BrowserNavigated(object sender, NavigationEventArgs e)
{
if (e.Uri.ToString().Contains("oauth_verifier="))
{
OAuthUtil.UpdateOAuthParametersFromCallback(e.Uri.ToString(), m_parameters);
Close();
}
}
at the last line (OAuthUtil.GetAccessToken(parameters);) I am getting a 400 bad request error and I have no idea why...
After much playing around... I think this is the easiest way to access google api:
Service service = new ContactsService("My Contacts Application");
service.setUserCredentials("mail#gmail.com", "password");
var token = service.QueryClientLoginToken();
service.SetAuthenticationToken(token);
var query = new ContactsQuery(#"https://www.google.com/m8/feeds/contacts/mail#gmail.com/full?max-results=25000");
var feed = (ContactsFeed)service.Query(query);
Console.WriteLine(feed.Entries.Count);
foreach (ContactEntry entry in feed.Entries)
{
Console.WriteLine(entry.Title.Text);
}
much easier than using oauth...
Related
I have been working with Linq2Twitter (v. 2), using the Search API and
I wanted to switch to the Stream API. I updated to v. 3 but since then I don't manage to authenticate anymore. I don't think the Stream API or the version could be the problem, because I've tried to go back to the previous version, previous authentication methods, and it doesn't work anymore either. I get a 401 : bad authentication data.
So, here is my current code :
var auth = new SingleUserAuthorizer
{
CredentialStore = new SingleUserInMemoryCredentialStore()
{
ConsumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"],
OAuthToken = ConfigurationManager.AppSettings["twitterOAuthToken"],
AccessToken = ConfigurationManager.AppSettings["twitterAccessToken"]
}
};
TwitterContext _twitterCtx = new TwitterContext(auth);
try
{
var verifyResponse =
await
(from acct in _twitterCtx.Account
where acct.Type == AccountType.VerifyCredentials
select acct)
.SingleOrDefaultAsync();
if (verifyResponse != null && verifyResponse.User != null)
{
User user = verifyResponse.User;
Console.WriteLine(
"Credentials are good for {0}.",
user.ScreenNameResponse);
}
}
catch (TwitterQueryException tqe)
{
Console.WriteLine(tqe.Message);
}
Of course, I checked the credentials several times, printed them out and all.
I tried with ApplicationOnlyAuthorizer, v.2, v.3 as well, it doesn't change anything.
What scares me the most is that what used to work (v2 + ApplicationOnly + Search API) doesn't work either.
Through my research I've heard of a problem caused by unsynchronized timestamps, or something like that. But I don't understand how I can change that.
The program is not on a server, it's locally stored.
Thank you for reading.
Here's how to use SingleUserAuthorizer in v3.0:
var auth = new SingleUserAuthorizer
{
CredentialStore = new SingleUserInMemoryCredentialStore
{
ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"],
AccessToken = ConfigurationManager.AppSettings["accessToken"],
AccessTokenSecret = ConfigurationManager.AppSettings["accessTokenSecret"]
}
};
Notice here that I'm setting AccessToken and AccessToken secret. I also have a FAQ with suggestions for resolving 401 problems:
https://linqtotwitter.codeplex.com/wikipage?title=LINQ%20to%20Twitter%20FAQ&referringTitle=Documentation
I've been trying to list users in my google apps domain for a while now.
No problem in Python, but in C# i get an error message:
An error has occured:
Google.Apis.Requests.RequestError
Bad Request [400]
Errors [
Message[Bad Request] Location[ - ] Reason[badRequest] Domain[global]
]
I'm no C# guru of any sorts but when I looked through the Google.Apis.Admin.directory_v1.cs - file it looked to me as if the UserResource ListRequest is wrong???
It's found on line 7349-7352 in the file. Anyone know's if it's not yet implemented in the API?
Edit:
I start with why I THINK the code in Google.Apis.Admin.directory_v1.cs, lines 7349-7352 is wrong(as I mentioned - I'm not a C#-guru):
The Code:
/// <summary>Retrieve either deleted users or all users in a domain (paginated)</summary>
public virtual ListRequest List() {
return new ListRequest(service);
}
Why I find it odd:
I can' see where to pass the customerid or domain as an argumant to this request, but in the APIs Explorer it's needed (otherwise I get the same error message as above, in my original post).
Edit : I looked a bit further down in the file and I guess that line 8904 and onwards is doing what I looked for earlier. My Bad!
But still I can't get my code to work?!?!?
And my code that won't work:
static void Main(string[] args)
{
// Display the header and initialize the sample.
CommandLine.EnableExceptionHandling();
Console.WriteLine("List users in a google apps domain!");
Console.WriteLine("by Jonas Bergstedt 2013");
// Get the domainname
Console.Write("Domain: ");
string domain = Console.ReadLine();
// Register the authenticator.
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description)
{
ClientIdentifier = <myClientId>,
ClientSecret = <myClientSecret>",
};
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
// Create the service.
var service = new DirectoryService(new BaseClientService.Initializer()
{
Authenticator = auth,
ApplicationName = "List Users",
ApiKey = <myApiKey>
});
// Trying to add the domain
service.Users.List().Domain = domain;
Users results = service.Users.List().Execute();
foreach (User list in results.UsersValue)
{
Console.WriteLine("- " + list.Name);
}
}
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
// Get the auth URL:
IAuthorizationState state = new AuthorizationState(new[] { DirectoryService.Scopes.AdminDirectoryUser.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
Console.WriteLine();
Console.Write("Authorization Code: ");
string authCode = Console.ReadLine();
// Retrieve the access token by using the authorization code:
return arg.ProcessUserAuthorization(authCode, state);
}
}
ListRequest had those properties. It looks like those properties aren't mandatory, so they aren't part of the constructor.
You can do the following:
var listReq = service.Users.List();
listReq.Customer = "CUSTOMER_HERE";
listReq.Domain = "DOMAIN_HERE";
Users results = listReq.Execute();
I've spent some time over the last few days trying to implement a feature for my web application. The feature should add new events to a users google calendar while they are offline. I read the Google OAuth2 documentation for web server applications and seem to understand the basics of it. I created a link to authorize the application for offline access:
<a target='_blank' href='https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Ftasks&response_type=code&client_id=<MY CLIENT ID>&access_type=offline&redirect_uri=http%3A%2F%2Flocalhost:49949%2Foauth2callback.aspx'>Grant Tasks Permission</a>
If the user accepts then I capture the refresh token at the redirect uri like this:
private static OAuth2Authenticator<WebServerClient> _authenticator;
protected void Page_Load(object sender, EventArgs e)
{
if (HttpContext.Current.Request["code"] != null)
{
_authenticator = CreateAuthenticator();
_authenticator.LoadAccessToken();
}
Response.Write("Refresh Token: " + _authenticator.State.RefreshToken);
}
private OAuth2Authenticator<WebServerClient> CreateAuthenticator()
{
var provider = new WebServerClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = "<MY CLIENT ID>";
provider.ClientSecret = "<MY CLIENT SECRET>";
return new OAuth2Authenticator<WebServerClient>(provider, GetAuthorization);
}
private IAuthorizationState GetAuthorization(WebServerClient client)
{
return client.ProcessUserAuthorization(new HttpRequestInfo(HttpContext.Current.Request));
}
For testing purposes I have been copying the refresh token to a text file for further use.
My problem is using this refresh token for offine access. I have been using this code to refresh the token:
protected void btnGetTasks_Click(object sender, EventArgs e)
{
if (_service == null)
{
_authenticator = CreateAuthenticator();
_service = new TasksService(new BaseClientService.Initializer() { Authenticator = _authenticator });
}
var cl = _service.Tasklists.List().Fetch();
}
private OAuth2Authenticator<WebServerClient> CreateAuthenticator()
{
// Register the authenticator.
var provider = new WebServerClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = "<MY CLIENT ID>";
provider.ClientSecret = "<MY CLIENT SECRET>";
var authenticator = new OAuth2Authenticator<WebServerClient>(provider, GetAuthorization);
return authenticator;
}
private IAuthorizationState GetAuthorization(WebServerClient client)
{
string scope = "https://www.googleapis.com/auth/tasks";
IAuthorizationState state = new AuthorizationState(new[] { scope });
state.RefreshToken = "<REFRESH TOKEN FROM FIRST STEP>";
var result = client.RefreshToken(state);
return client.ProcessUserAuthorization();
}
Everything seems fine at this point. When I step through the code I can see the result from client.RefreshToken(state) is true. The issue is when I call this line of code:
_service.Tasklists.List().Fetch();
It returns a (401) unauthorized error from google. I'm looking into the cause but I am not sure how to proceed and I am running short on time with this feature. Any advice would be greatly appreciated. Thanks!
Seems just the act of putting code on here always helps me figure it out a little sooner :)
It now appears this line is unnecessary:
return client.ProcessUserAuthorization();
removing that from the GetAuthorization method and just returning the state passed to RefreshToken has resolved the unauthorized error. I'll leave the question in case it stumps anyone else.
Coding Platform ASP.NET 4.0 WebForms
I have two pages that are relevant here
Login.aspx
LandingPage.aspx
On Login.aspx when I click an ImageButton, I redirect to Facebook site with the following code
protected void FacebookLoginButton_Click(object sender, ImageClickEventArgs e)
{
try
{
Response.Redirect(GetFacebookLoginURL());
}
catch (System.Threading.ThreadAbortException)
{
throw;
}
catch (Exception err)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(err);
}
}
private string GetFacebookLoginURL()
{
try
{
string baseURL = System.Configuration
.ConfigurationManager
.AppSettings["WebsiteURL"]
.ToString();
string[] extendedPermissions = new[] {
"publish_stream",
"offline_access"
};
var oauth = new FacebookOAuthClient {
ClientId = FacebookContext.Current.AppId
};
var parameters = new Dictionary<string, object>{
{ "response_type", "token" },
{ "display", "page" }
};
if (extendedPermissions != null && extendedPermissions.Length > 0)
{
var scope = new StringBuilder();
scope.Append(string.Join(",", extendedPermissions));
parameters["scope"] = scope.ToString();
}
parameters["redirect_uri"] = String.Format("{0}LandingPage.aspx", baseURL);
return oauth.GetLoginUrl(parameters).OriginalString;
}
catch (Exception err)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(err);
return "";
}
}
That part is working properly. But I am clueless on how to access the user info at the LandingPage which is my redirect_uri. Have tried this.
FacebookOAuthClient cl = new FacebookOAuthClient(FacebookContext.Current);
FacebookOAuthResult result = null;
string url = Request.Url.AbsoluteUri;
// verify that there is a code in the url
if (FacebookOAuthResult.TryParse(url, out result))
{
if (result.IsSuccess)
{
var accesstoken = result.AccessToken;
}
else
{
var errorDescription = result.ErrorDescription;
var errorReason = result.ErrorReason;
}
}
But I doubt it wont work since I dont have window.hash.location at Server Side(Its not working anyway)
var client = new FacebookClient(FacebookContext.Current);
dynamic me = client.Get("me");
string firstName = me.first_name;
string lastName = me.last_name;
string email = me.email;
Although I am not sure, getting the Access Token will solve my problem, won't it?
This is the error I am getting.
(OAuthException) An active access
token must be used to query
information about the current user.
What am I doing wrong?
here's a sample of a standalone website using webforms. Check out Default.aspx.cs and Web.config. Please note that this sample could be modified for use with the latest source code and might not work with the latest release (5.0.3 beta).
I just recently did this implementation. To access "me", you need to have an Access Token.
The implementation is pretty straighforward, however, I will say that I found the major stumbling block for me was to make sure that my redirect_uri from my "Login.aspx" url matched the redirect_uri from my landing page.
It must be simple, but I dodnt get it. So I used the lesser used Facebook C# SDK by Facebook. I pretty much did what this blog suggested. Everything is fine now.
My facebook app uses the Facebook C# SDK to publish to a user's Facebook profile. I'm currently publishing multiple posts with one attachment, but I'd much rather publish one summary post with multiple attachments. I've done this with the JavaScript API, but is it possible with the C# SDK?
This is my current publish code:
FacebookApp app = new FacebookApp(user.AccessToken);
string userFeedPath = String.Format("/{0}/feed/", user.FacebookUserId);
string message = String.Format("{0} earned an achievement in {1}",
user.SteamUserId, achievement.Game.Name);
dynamic parameters = new ExpandoObject();
parameters.link = achievement.Game.StatsUrl;
parameters.message = message;
parameters.name = achievement.Name;
parameters.description = achievement.Description;
parameters.picture = achievement.ImageUrl;
app.Api(userFeedPath, parameters, HttpMethod.Post);
We currently don't support multiple attachments. As far as I know you can't publish multiple attachments with either the graph or rest api. If you have a sample that shows how to do it, I will get it implemented in the SDK.
i have the same code as yours but it doesent work for me. I am trying this:
public void plesni()
{
try
{
dynamic parameters = new ExpandoObject();
parameters.message = "xxxxxxx";
parameters.link = "xxxxxxxx";
// parameters.picture=""
parameters.name = "xxxxxx";
parameters.caption = "xxxxxxx";
parameters.description = "xxxxxxxxxx";
parameters.actions = new
{
name = "xxxxxxx",
link = "http://www.xxxxxxxxxxxxxx.com",
};
parameters.privacy = new
{
value = "ALL_FRIENDS",
};
parameters.targeting = new
{
countries = "US",
regions = "6,53",
locales = "6",
};
dynamic result = app.Api("/uid/feed/", parameters, HttpMethod.Post);
// app.Api("/uid/feed", parameters);
Response.Write("Sucess");
}
catch (FacebookOAuthException)
{
Response.Write("...... <br/>");
}
}
if instead of uid I put me it works fine.
I am hoping for your help.
Have a good day.