My application connects to Jira for data extraction. To do that, I used the following code:
public string RunQuery(JiraRessource resource, string project_id, int startAt, int maxResults, string method = "GET")
{
string url = string.Format(m_BaseUrl);
if (project_id != null)
{
string jql = "search?jql=project=" + project_id;
url = string.Format("{0}{1}", url, jql);
}
string jqr = "&startAt=" + startAt + "&maxResults=" + maxResults;
url = string.Format("{0}{1}", url, jqr);
Console.WriteLine(url);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "application/json";
request.Method = method;
string base64Credentials = GetEncodedCredentials();
//string base64Credentials = WindowsIdentity.GetCurrent().Token.ToString();
request.Headers.Add("Authorization", "Basic " + base64Credentials);
string result = string.Empty;
using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
return result;
}
}
}
private string GetEncodedCredentials()
{
string mergedCredentials = string.Format("{0}:{1}", m_username, m_password);
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
return Convert.ToBase64String(byteCredentials);
}
The user has to enter the username and the password to connect. I want to change that in order to connect directly using windows credentials. I have no idea on how to do that. Is it possible? If it is, how can I do that?
WebRequest class has a Credentials property. You can set it with a new NetworkCredential object. You can also set it to logged in windows user. Sample code;
request.Credentials = new NetworkCredential(user, pwd, domain);
or
request.Credentials = CredentialCache.DefaultNetworkCredentials;
Related
How do I test if user supplied correct username/password for basic authentication?
I have this code to retrieve a page. If authentication is valid, it works fine
public static bool can_login(string user_name, string password)
{
WebResponse response = null;
StreamReader reader = null;
string result = null;
string login_url = "https://httpbin.org/basic-auth/user/passwd";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(login_url);
request.Method = "GET";
// Set the basic auth
string authInfo = user_name + ":" + password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
response = request.GetResponse(); // Throws System.Net.WebException if login invalid
reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
result = reader.ReadToEnd();
return false;
}
Is there a foolproof way to test for correctness or should I just catch exception and hope its about the credentials?
Edit: I wanted to come back to note that the problem wasn't on my end at all, but rather with with code on the other company's side.
I'm trying to pull up a page using Basic Authentication. I keep getting a 404 Page not found error. I can copy and paste my url into the browser and it works fine (if I'm not logged into their site already it pops up a credential box, otherwise it opens what I want it to open). I must be getting to the right place and authenticating, because I get a 401 (not authenticated error) if I intentially put in a bad username/password and I get an internal server error 500 if I pass it a bad parameter in the query string. I've tried using Webclient and HttpWebRequest both leading to the same 404 not found error.
With Webclient:
string url = "MyValidURLwithQueryString";
WebClient client = new WebClient();
String userName = "myusername";
String passWord = "mypassword";
string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(userName + ":" + passWord));
client.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials;
var result = client.DownloadString(url);
Response.Write(result);
With HttpWebRequest
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("MyValidURL");
string authInfo = "username:password";
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Headers.Add("Authorization", "Basic " + authInfo);
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Http.Get;
request.AllowAutoRedirect = true;
request.Proxy = null;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader streamreader = new StreamReader(stream);
string s = streamreader.ReadToEnd();
Response.Write(s);
//BEWARE
//This works ONLY if the server returns 401 first
//The client DOES NOT send credentials on first request
//ONLY after a 401
client.Credentials = new NetworkCredential(userName, passWord); //doesnt work
//So use THIS instead to send credentials RIGHT AWAY
string credentials = Convert.ToBase64String(
Encoding.ASCII.GetBytes(userName + ":" + password));
client.Headers[HttpRequestHeader.Authorization] = string.Format(
"Basic {0}", credentials);
Try changing the Web Client request authentication part to:
NetworkCredential myCreds = new NetworkCredential(userName, passWord);
client.Credentials = myCreds;
Then make your call, seems to work fine for me.
This part of code worked fine for me:
WebRequest request = WebRequest.Create(url);
request.Method = WebRequestMethods.Http.Get;
NetworkCredential networkCredential = new NetworkCredential(logon, password); // logon in format "domain\username"
CredentialCache myCredentialCache = new CredentialCache {{new Uri(url), "Basic", networkCredential}};
request.PreAuthenticate = true;
request.Credentials = myCredentialCache;
using (WebResponse response = request.GetResponse())
{
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
using (Stream dataStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(dataStream))
{
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);
}
}
}
If its working when you are using a browser and then passing on your username and password for the first time - then this means that once authentication is done Request header of your browser is set with required authentication values, which is then passed on each time a request is made to hosting server.
So start with inspecting Request Header (this could be done using Web Developers tools), Once you established whats required in header then you could pass this within your HttpWebRequest Header.
Example with Digest Authentication:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
namespace NUI
{
public class DigestAuthFixer
{
private static string _host;
private static string _user;
private static string _password;
private static string _realm;
private static string _nonce;
private static string _qop;
private static string _cnonce;
private static DateTime _cnonceDate;
private static int _nc;
public DigestAuthFixer(string host, string user, string password)
{
// TODO: Complete member initialization
_host = host;
_user = user;
_password = password;
}
private string CalculateMd5Hash(
string input)
{
var inputBytes = Encoding.ASCII.GetBytes(input);
var hash = MD5.Create().ComputeHash(inputBytes);
var sb = new StringBuilder();
foreach (var b in hash)
sb.Append(b.ToString("x2"));
return sb.ToString();
}
private string GrabHeaderVar(
string varName,
string header)
{
var regHeader = new Regex(string.Format(#"{0}=""([^""]*)""", varName));
var matchHeader = regHeader.Match(header);
if (matchHeader.Success)
return matchHeader.Groups[1].Value;
throw new ApplicationException(string.Format("Header {0} not found", varName));
}
private string GetDigestHeader(
string dir)
{
_nc = _nc + 1;
var ha1 = CalculateMd5Hash(string.Format("{0}:{1}:{2}", _user, _realm, _password));
var ha2 = CalculateMd5Hash(string.Format("{0}:{1}", "GET", dir));
var digestResponse =
CalculateMd5Hash(string.Format("{0}:{1}:{2:00000000}:{3}:{4}:{5}", ha1, _nonce, _nc, _cnonce, _qop, ha2));
return string.Format("Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", " +
"algorithm=MD5, response=\"{4}\", qop={5}, nc={6:00000000}, cnonce=\"{7}\"",
_user, _realm, _nonce, dir, digestResponse, _qop, _nc, _cnonce);
}
public string GrabResponse(
string dir)
{
var url = _host + dir;
var uri = new Uri(url);
var request = (HttpWebRequest)WebRequest.Create(uri);
// If we've got a recent Auth header, re-use it!
if (!string.IsNullOrEmpty(_cnonce) &&
DateTime.Now.Subtract(_cnonceDate).TotalHours < 1.0)
{
request.Headers.Add("Authorization", GetDigestHeader(dir));
}
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
// Try to fix a 401 exception by adding a Authorization header
if (ex.Response == null || ((HttpWebResponse)ex.Response).StatusCode != HttpStatusCode.Unauthorized)
throw;
var wwwAuthenticateHeader = ex.Response.Headers["WWW-Authenticate"];
_realm = GrabHeaderVar("realm", wwwAuthenticateHeader);
_nonce = GrabHeaderVar("nonce", wwwAuthenticateHeader);
_qop = GrabHeaderVar("qop", wwwAuthenticateHeader);
_nc = 0;
_cnonce = new Random().Next(123400, 9999999).ToString();
_cnonceDate = DateTime.Now;
var request2 = (HttpWebRequest)WebRequest.Create(uri);
request2.Headers.Add("Authorization", GetDigestHeader(dir));
response = (HttpWebResponse)request2.GetResponse();
}
var reader = new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
}
Then you could call it:
DigestAuthFixer digest = new DigestAuthFixer(domain, username, password);
string strReturn = digest.GrabResponse(dir);
if Url is: http://xyz.rss.com/folder/rss then domain: http://xyz.rss.com (domain part) dir: /folder/rss (rest of the url)
you could also return it as stream and use XmlDocument Load() method.
I am triyng to get data from the Rest API. API wants 3 things to give authentication;
first one is "Accept:application/vnd.###.v1.0+json"
second one : "Content Type : application/json"
third one : Base64 encoded "userName:password" string
and I should pass these credentials for validation and authorization in custom header.I know there are a lot of thread on this site about this topic but I couldn't solve the problem from them.
Here is the code block :
public class McAfeeIPSManager
{
String URL = "https://serviceOfApi/sdkapi/session";
public void getWebRequest()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
String username = "user";
String password = "password1";
var request = HttpWebRequest.Create(URL) as HttpWebRequest;
request.Accept = "application/vnd.###.v2.0+json";
request.Method = "GET";
request.ContentType = "application/json";
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
request.Headers.Add("Authorization","Basic "+encoded);
try
{
// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
using (var responseReader = new StreamReader(response.GetResponseStream()))
{
string responseBody = responseReader.ReadToEnd();
// Console application output
System.Diagnostics.Debug.Write("Response Body ---> " + responseBody);
//Console.WriteLine(responseBody);
}
}
}
catch (WebException ex)
{
System.Diagnostics.Debug.Write("Error : " + ex.Message);
Console.WriteLine("Error: {0}", ex.Message);
}
}
}
How can get data from WebAPI under these conditions?Can anybody help me?
You have no PreAuthenticate and credential ?
I have a code that may help you:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://pwmaffr2:8443/remote/system.delete?names=" + DeviceName + "");
request.Headers.Add("AUTHORIZATION", "Basic YTph");
request.ContentType = "text/html";
request.Credentials = new NetworkCredential(Username, Password);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
request.PreAuthenticate = true;
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
);
StreamReader stream = new StreamReader(response.GetResponseStream());
string X = stream.ReadToEnd();
hmm in addition of what i post try deal with this it should work for you hope:
string credentials = String.Format("{0}:{1}", username, password);
byte[] bytes = Encoding.ASCII.GetBytes(credentials);
string base64 = Convert.ToBase64String(bytes);
string authorization = String.Concat("basic ", base64);
request.Headers.Add("Authorization", authorization);
I am trying to read the source from a page that requires basic authentication. However, using a Header and even Credentials in my HttpWebRequest, I still get a Unauthorized Exception [401] returned.
string urlAddress = URL;
string UserName = "MyUser";
string Password = "MyPassword";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlAddress);
if (UserName != string.Empty)
{
string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(UserName + ":" + Password));
request.Headers.Add("Authorization", "Basic " + encoded);
System.Net.CredentialCache credentialCache = new System.Net.CredentialCache();
credentialCache.Add(
new System.Uri(urlAddress), "Basic", new System.Net.NetworkCredential(UserName, Password)
);
request.Credentials = credentialCache;
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); //<== Throws Exception 401
Fiddler Auth Results
No Proxy-Authenticate Header is present.
WWW-Authenticate Header is present: Basic realm="example"
As message says:
No Proxy-Authenticate Header is present.
Then, the workaround:
...
string urlAddress = "http://www.google.com";
string userName = "user01";
string password = "puser01";
string proxyServer = "127.0.0.1";
int proxyPort = 8081;
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(urlAddress);
if (userName != string.Empty)
{
request.Proxy = new WebProxy(proxyServer, proxyPort)
{
UseDefaultCredentials = false,
Credentials = new NetworkCredential(userName, password)
};
string basicAuthBase64 = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(string.Format("{0}:{1}", userName, password)));
request.Headers.Add("Proxy-Authorization", string.Format("Basic {0}", basicAuthBase64));
}
using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
{
var stream = response.GetResponseStream();
if (stream != null)
{
//--print the stream content to Console
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
}
}
...
I hope it helps.
I am encountering a problem getting the access_token in client application using oauth.
The returned response has empty body though in API I can see the response is not empty.
tokenresponse = {
"access_token":"[ACCESSTOKENVALUE]",
"token_type":"bearer",
"expires_in":"1200",
"refresh_token":"[REFRESHTOKENVALUE]",
"scope":"[SCOPEVALUE]"
}
The method from API that returns the token http://api.sample.com/OAuth/Token:
public ActionResult Token()
{
OutgoingWebResponse response =
this.AuthorizationServer.HandleTokenRequest(this.Request);
string tokenresponse = string.Format("Token({0})", response!=null?response.Body:""));
return response.AsActionResult();
}
The client method that requests the token is:
public string GetAuthorizationToken(string code)
{
string Url = ServerPath + "OAuth/Token";
string redirect_uri_encode = UrlEncode(ClientPath);
string param = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",code, ClientId, ClientSecret, redirect_uri_encode);
HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
string result = null;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = 10000;
request.Headers.Remove(HttpRequestHeader.Cookie);
var bs = Encoding.UTF8.GetBytes(param);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse response = request.GetResponse())
{
var sr = new StreamReader(response.GetResponseStream());
result = sr.ReadToEnd();
sr.Close();
}
if (!string.IsNullOrEmpty(result))
{
TokenData tokendata = JsonConvert.DeserializeObject<TokenData>(result);
return UpdateAuthorizotionFromToken(tokendata);
}
return null;
}
The result variable is empty.
Please let me know if you have any idea what could cause this. Initially I assumed is because of the cookies so I tried to remove them from request.
Thanks in advance.
Dear just create webclient using following code and you will get json info in tokeninfo.I used it and simply its working perfect.
WebClient client = new WebClient();
string postData = "client_id=" + ""
+ "&client_secret=" + ""
+ "&grant_type=password&username=" + "" //your username
+ "&password=" + "";//your password :)
string soundCloudTokenRes = "https://api.soundcloud.com/oauth2/token";
string tokenInfo = client.UploadString(soundCloudTokenRes, postData);
You can then use substring that contains only token from tokeninfo.
To upload tracks on sound cloud.
private void TestSoundCloudupload()
{
System.Net.ServicePointManager.Expect100Continue = false;
var request = WebRequest.Create("https://api.soundcloud.com/tracks") as HttpWebRequest;
//some default headers
request.Accept = "*/*";
request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");
request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
request.Headers.Add("Accept-Language", "en-US,en;q=0.8,ru;q=0.6");
//file array
var files = new UploadFile[] { new UploadFile(Server.MapPath("Downloads//0.mp3"), "track[asset_data]", "application/octet-stream") };
//other form data
var form = new NameValueCollection();
form.Add("track[title]", "Some title");
form.Add("track[sharing]", "public");
form.Add("oauth_token", "");
form.Add("format", "json");
form.Add("Filename", "0.mp3");
form.Add("Upload", "Submit Query");
try
{
using (var response = HttpUploadHelper.Upload(request, files, form))
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
Response.Write(reader.ReadToEnd());
}
}
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}