Bounty Question
I am using c# 3.5 Window Forms Application. I am using the code mentioned in the accepted answer. and I am getting below error
The remote server returned an error: (401) Unauthorized.
Sample code to verify the UserName and Password will be really appreciated
Bounty Question Ends
I have an application with the following use-case: when the user first starts using the application, he inputs his username and password. Then, at a much later stage, the application may update his status.
Currently I'm using Twitterizer, but I believe the question is beyond the scope of the specific library I'm using. Following are the two relevant lines of code:
Twitter twitter = new Twitter("username", "password", "source");
twitter.Status.Update("update");
The construction of the Twitter object does not throw an exception if the username/password are incorrect. This is probably because nothing is sent at this point. On the other hand, the status update does throw an exception if the username/password are invalid.
My problem is that I want to validate the username/password at the point of user input, not when trying to post the update.
How can I validate the username/password without posting anything (in Twitterizer or otherwise)?
Taking a quick look at the verify_credentials API as mentioned by peSHIr, I wrote a little routine which seems to do the trick. It's late, but I was able to test it a couple of times and seems to work.
In my function, I am just returning true if I I get an HttpResponseCode.OK, and false if I get anything else or an exception is thrown. If twitter does not like the uid/password an exception will be thrown with a 401 error (not authorized.)
public bool CheckTwitterCredentials(string UserName, string Password)
{
// Assume failure
bool Result = false;
// A try except block to handle any exceptions
try {
// Encode the user name with password
string UserPass = Convert.ToBase64String(
System.Text.Encoding.UTF8.GetBytes(UserName + ":" + Password));
// Create our HTTP web request object
HttpWebRequest Request =
(HttpWebRequest)WebRequest.Create("http://twitter.com/account/verify_credentials.xml");
// Set up our request flags and submit type
Request.Method = "GET";
Request.ContentType = "application/x-www-form-urlencoded";
// Add the authorization header with the encoded user name and password
Request.Headers.Add("Authorization", "Basic " + UserPass);
// Use an HttpWebResponse object to handle the response from Twitter
HttpWebResponse WebResponse = (HttpWebResponse)Request.GetResponse();
// Success if we get an OK response
Result = WebResponse.StatusCode == HttpStatusCode.OK;
} catch (Exception Ex) {
System.Diagnostics.Debug.WriteLine("Error: " + Ex.Message);
}
// Return success/failure
return Result;
}
You could try to use the API call account/verify_credentials. Hopefully the API library you use already supports this.. Twitter is notorious now for really hating third party programmers, so unless you have good reason to do something with Twitter, just stay away...
I have used other Twitter Libraries but none of them support checking the username and password for validitity. This might be because Twitter API does not have the facility to validate the username and password unless we try to do something which requires authentication.
One thing you can do is try to get friend list or any other methods that requires authentication.
Twitter API hasn't supported username/password in years. Instead, you have OAuth, which lets the user authorize your application to act on their behalf. Twitter has an account/verify_credentials endpoint you can use to verify whether the user who's tokens you have still authorizes your app. Here's an example of how you could call this endpoint with LINQ to Twitter:
var accounts =
from acct in twitterCtx.Account
where acct.Type == AccountType.VerifyCredentials
select acct;
You can visit Account/VerifyCredentials documentation for more details:
as #joe-mayo informed, you have to switch to OAuth. twitter expired v1 of their API and they documented that in following url https://dev.twitter.com/docs/faq#17750.
Here's a function i wrote that will verify twitter username and password in C# :
public bool isTwitterValid(string username, string password)
{
try
{
string user = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(username + ":" + password));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://twitter.com/statuses/verify.xml");
request.Method = "POST";
request.ServicePoint.Expect100Continue = false;
request.Headers.Add("Authorization", "Basic " + user);
request.ContentType = "application/x-www-form-urlencoded";
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseString = reader.ReadToEnd();
reader.Close();
}
catch (Exception ex)
{
if (ex.Message.Contains("404")) { return true; }
}
return false;
}
Related
I'm trying to create an application that allows users to create preferred playlists on spotify. I am using the spotify web api and building an asp.net mvc application (c#). I am trying to make the web request to have users login to their spotify account, but for some reason my app does not redirect to the login page whenever I try to get the response.
I have tried creating a redirect link myself, but shouldn't the GetResponse() method invoke the redirect itself? I am new at this so I may be wrong but any help would be appreciated.
public IActionResult GetLogin()
{
string spotifyURL = "https://accounts.spotify.com/authorize/";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(spotifyURL);
webRequest.Method = "GET";
webRequest.Headers["client_id"] = clientID;
webRequest.Headers["response_type"] = "code";
webRequest.Headers["redirect_uri"] = "https://localhost:44383/home/login";
string json = "";
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader rdr = new StreamReader(stream, Encoding.UTF8))
{
//should get back a string i can then turn to json and parse for accesstoken
json = rdr.ReadToEnd();
rdr.Close();
}
}
}
bool authorized = true;
if (authorized)
{
return View("Callback");// token.access_token;
}
else
{
return View("Home");
}
}
As I understand you are trying to authentificate on spotify.
I can tell you you have a few mistakes you are using a GET method tho authentificate
- The service waits a POST from you in JSON with account data like login and password, if the login and password and format will be correct it return you a JSON with access token.
How to add a Header format: Headers.Add(HttpRequestHeader.ContentType = "application/json");
After this the server will understand what content you actually sending to it.
A little about the last parts of code:
bool authorized = true;
if (authorized)
{
return View("Callback");// token.access_token;
}
else
{
return View("Home");
}
You returning like a blank Views here it is better to use
return RedirectToAction("ActionName", "CpntrollerName", new { "Here you can pass any value" });
This will allow you to redirect to another Controller and View and pass a value to it.
Summary is:
I could write a long time but better to tell the real problem you should read more on how to use API in C# applications.
Here I will provide you some links on MS documentations:
The WebRequest method: link
The HttpClient method: link
About HttpClient I recommend to use it only on desktop or mobile apps because it inherits from .NET Framework and not from .NET Core so it may cause an errors, but I didn't do a test on my ASP.NET Core applications so can't say for sure.
Little tips:
Use Newtonsoft.Json it will help you to serialize your JSON request and deserialize answer it is much easier then do it with your hands or Regex.
Use async and Task when making requests to the web, because answer can be long waited, and you don't want your app stay frozen until it waits an answer.
I'm trying to connect to jsonwhoisapi.com to drag down some whois data, but am having no luck. Has anyone done this or done something similar and can help spot my folly? I've never done an api connection using HTTP headers.
I've basically copied this from a post online where it was apparently working, but the following dies at GetResponseStream.
public static void WebRequest()
{
string WEBSERVICE_URL = "https://jsonwhoisapi.com/api/v1/whois?identifier=google.com";
try
{
var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
if (webRequest != null)
{
webRequest.Method = "GET";
webRequest.Timeout = 20000;
webRequest.ContentType = "application/json";
webRequest.Headers.Add("userid:apikey");
using (System.IO.Stream s = webRequest.GetResponse().GetResponseStream())
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(s))
{
var jsonResponse = sr.ReadToEnd();
Console.WriteLine(String.Format("Response: {0}", jsonResponse));
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
My guess is you'll have to replace 'apikey' with your ApiKey string, and userId with your CustomerId string.
Direct quote:
With every request you must send the [customer ID:API key] pair to authenticate - both pieces of information can be found when logged in to you account.
Chances are you might have to encode the auth request using the instructions here: https://en.wikipedia.org/wiki/Basic_access_authentication#Protocol
Client side:
When the user agent wants to send the server authentication
credentials it may use the Authorization field.
The Authorization field is constructed as follows:
The username and password are combined with a single colon. (:)
The resulting string is encoded into an octet sequence.
The resulting string is encoded using a variant of Base64.
The authorization method and a space is then prepended to the encoded string, separated with a space (e.g. "Basic ").
For example, if the browser uses Aladdin as the username and
OpenSesame as the password, then the field's value is the
base64-encoding of Aladdin:OpenSesame, or QWxhZGRpbjpPcGVuU2VzYW1l.
Then the Authorization header will appear as:
Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l
e.g. Something like:
webRequest.Headers.Add(string.Format("Authorization: Basic {0}", Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", userId, apiKey)))));
EDIT
This question was for a workaround. Getting a successful login by using HttpWebRequests. Not on how to use the api.
Question
I noticed in the API there was no way to get a usernames password.
This is what I have now as a test. I thought I could just get the "Wrong user/pass" response first and go from there. All I get is the pages source code.
Anyone have any pointers or advice?
I am definitively logging in. In Account Admin and Login History, it shows me logging in. But the server is not serving any useful response text for the login. And now, I locked myself out using wrong passwords to sort through the streamreader lol.
public string DoVerification(string email, string password)
{
var request = (HttpWebRequest)WebRequest.Create("https://app.smartsheet.com/b/home");
var postData = "loginEmail=" + email;
postData += "&loginPassword=" + password;
postData += "&action=login";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
return new StreamReader(response.GetResponseStream()).ReadToEnd();
}
private void btnLogin_Click(object sender, EventArgs e)
{
string response = DoVerification("test#test.com", "12345");
MessageBox.Show(response.ToString());
}
It's unclear what you are trying to achieve or why you expect it to work.
There is no way to retrieve a password through the API. That would be a bad idea.
You aren't actually using the API. API endpoints start with https://api.smartsheet.com/2.0 and are documented here: http://smartsheet-platform.github.io/api-docs/
After comparing both sources from the returned response.
I have these two js functions.
Failed attempt
function loggedFailures() {
logExternalGTMEvent({'event': 'app-login-failure','method': 'onsite','error': 'AUTH_NO_MATCHING_USER'}); return true
}
Successful attempt
function loggedFailures() {
return false
}
I just simply check for one or the other.
And for the record, putting the users password in the api is not a bad idea.... Smartsheets lets us delete any user through the API, so I don't see what it would matter.
I pretend to integrate my website with facebook, whant to make a automatic post (on a specific facebook account) while a user interacts with a web application.
is there any way to make this operation like a webservice way?, authenticating and calling a url that posts the information i send directly on the facebook wall?
i'm using asp.net mvc3 C# i've found a facebook developer toolkit library, is this the correct way to start or what should i do?
What is necessary is only write a post automatically on a facebook account, for example when i write a new article (news) on my website, it will be automatically posted on fb.
any idea to get me started?
I did something kind of similar, when a user clicks on a "share" button on my mvc app, it posts something on his wall. The problem using the oauth dialog, is that it will redirect the browser to a facebook site for the user to log in and accept the application permissions.
On the "share" button, I linked it to this url:
<a href=""https://www.facebook.com/dialog/oauth?client_id=[YOUR_APP_ID]&redirect_uri=[THE_REDIRECT_PAGE]/&scope=publish_stream"">
<img src='#Url.Content("~/Images/facebook_share.png")' alt="Share on Facebook!" style="height:28px" />
</a>
YOUR_APP_ID is your facebook application ID.
THE_REDIRECT_PAGE is a public page on your site that facebook will automatically redirect once the user has logged in and accepted the permissions. When facebook redirects, it appends a querystring parameter called "code" to it.
NOTE: The redirect page MUST END with a "/", it cannot end with a document, or else it doesn't work!
Once the user has accepted your request, you must ask facebook another code, called access code, used to post on the user's wall.
This code is on the redirect page:
public ActionResult Index(string code)
{
string fbAuthCode = Request["code"]; //The authorization code.
string fbAppId = "XXXXXXX"; //Your fb application id.
string fbSecretAppId = "XXXXXXXXXXXXXXXXXXXXX"; //Your fb secret app id, it is found on the fb application configuration page.
string redirectUrl = string.Format("[THE_REDIRECT_PAGE]", locationPointId, entryLocationId); //The redirect url. THIS MUST BE THE EXACT SAME REDIRECT URL USED ON THE JAVASCRIPT LINK!
string fbUrl = "https://graph.facebook.com/oauth/access_token?client_id=" + fbAppId + "&redirect_uri=" + redirectUrl + "&client_secret=" + fbSecretAppId + "&code=" + fbAuthCode; //Url used to post.
string accessToken = string.Empty;
try
{
WebClient client = new WebClient();
using (Stream stream = client.OpenRead(fbUrl))
using (StreamReader reader = new StreamReader(stream))
{
accessToken = reader.ReadToEnd().Split('&')[0].Replace("access_token=", string.Empty);
reader.Close();
}
}
catch (Exception ex)
{
throw new Exception("An error ocurred while trying to get the fb token in " + fbUrl, ex);
}
Once you have the access token, you can post to the user wall:
string postUrl = "https://graph.facebook.com/me/feed";
string postParameters;
postParameters = string.Format("message={0}&picture={1}&name={2}&caption={2}&description={3}&link={4}&access_token={5}",
"[Message]",
"[PictureUrl]",
"[Name]",
"[Caption]",
"[Link]",
accessToken);
try
{
System.Net.WebRequest req = System.Net.WebRequest.Create(postUrl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(postParameters);
req.ContentLength = bytes.Length;
using (System.IO.Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length); //Push it out there
os.Close();
using (WebResponse resp = req.GetResponse())
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
ViewBag.PostResult = sr.ReadToEnd().Trim();
sr.Close();
}
os.Close();
}
}
catch (Exception ex)
{
throw new Exception("An error ocurred while posting data to the user's wall: " + postUrl + "?" + postParameters, ex);
}
return RedirectToAction(XXXXXXXXXXXxx....); //Then i redirect to another page.
You can see that on the exception I throw the posted url (for debugging purposes).
With that url you can usually go to the facebook Graph API Explorer or the Linter and check the real error.
I don't know if this is exactly what you want but hope it gives you a kickoff...
I've struggled a few days with this, because facebook documentation on open graph is not very good yet, at least for us that don't use curl :)
https://developers.facebook.com/docs/opengraph/tutorial/
https://developers.facebook.com/docs/opengraph/
Hope it helps.
MT.
It's easy:
Step 1:
Get a valid facebook token by requesting "*https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope="publish_stream,email*" (full list of permissions there: https://developers.facebook.com/docs/reference/api/user/)
Step 2:
Post your message to the user wall:
curl -F 'access_token=...' \
-F 'message=your message' \
https://graph.facebook.com/ID_OR_USERNAME/feed
I created RESTful webservice (WCF) where I check credentials on each request. One of my clients is Android app and everything seems to be great on server side. I get request and if it's got proper header - I process it, etc..
Now I created client app that uses this service. This is how I do GET:
// Create the web request
var request = WebRequest.Create(Context.ServiceURL + uri) as HttpWebRequest;
if (request != null)
{
request.ContentType = "application/json";
// Add authentication to request
request.Credentials = new NetworkCredential(Context.UserName, Context.Password);
// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
// Console application output
var s = reader.ReadToEnd();
var serializer = new JavaScriptSerializer();
var returnValue = (T)serializer.Deserialize(s, typeof(T));
return returnValue;
}
}
}
So, this code get's my resource and deserializes it. As you see - I'm passing credentials in my call.
Then when debugging on server-side I noticed that I get 2 requests every time - one without authentication header and then server sends back response and second request comes bach with credentials. I think it's bad for my server - I'd rather don't make any roundtrips. How should I change client so it doesn't happen? See screenshot of Fiddler
EDIT:
This is JAVA code I use from Android - it doesn't do double-call:
MyHttpResponse response = new MyHttpResponse();
HttpClient client = mMyApplication.getHttpClient();
try
{
HttpGet request = new HttpGet(serviceURL + url);
request.setHeader(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
request.addHeader("Authorization", "Basic " + Preferences.getAuthorizationTicket(mContext));
ResponseHandler<String> handler = new BasicResponseHandler();
response.Body = client.execute(request, handler);
response.Code = HttpURLConnection.HTTP_OK;
response.Message = "OK";
}
catch (HttpResponseException e)
{
response.Code = e.getStatusCode();
response.Message = e.getMessage();
LogData.InsertError(mContext, e);
}
The initial request doesn't ever specify the basic header for authentication. Additionally, since a realm is specified, you have to get that from the server. So you have to ask once: "hey, I need this stuff" and the server goes "who are you? the realm of answering is 'secure area'." (because realm means something here) Just because you added it here:
request.Credentials = new NetworkCredential(Context.UserName, Context.Password);
doesn't mean that it's going to be for sure attached everytime to the request.
Then you respond with the username/password (in this case you're doing BASIC so it's base64 encoded as name:password) and the server decodes it and says "ok, you're all clear, here's your data".
This is going to happen on a regular basis, and there's not a lot you can do about it. I would suggest that you also turn on HTTPS since the authentication is happening in plain text over the internet. (actually what you show seems to be over the intranet, but if you do go over the internet make it https).
Here's a link to Wikipedia that might help you further: http://en.wikipedia.org/wiki/Basic_access_authentication
Ok, I got it. I manually set HttpHeader instead of using request.Credentials
request.Headers.Add(HttpRequestHeader.Authorization, "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(Context.UserName + ":" + Context.Password)));
Now I see only single requests as expected..
As an option you can use PreAuthenticate property of HttpClientHandler. This would require a couple of lines more
var client = new HttpClient(new HttpClientHandler
{
Credentials = yourCredentials,
PreAuthenticate = true
});
With using this approach, only the first request is sent without credentials, but all the rest requests are OK.