A thousand apologies if this question has been posted already, but I am getting a "The remote server returned an error: (401) Unauthorized" error when attempting to upload a string to a remote server via a web request in SSIS (Visual Studio) by means of a script task - the external company to whom I am sending the data are certain that my public IP and the user credentials I am using to authenticate all have access to the server.
My code looks like this;
public void Main()
{
string proxyServer = (string)Dts.Variables["$Project::ProxyServer"].Value;
int proxyPort = (int)Dts.Variables["$Project::ProxyPort"].Value;
string username = Convert.ToString(Dts.Variables["$Project::UserName"].Value);
string password = Convert.ToString(Dts.Variables["$Project::Password"].GetSensitiveValue());
Uri TargetSite = new Uri((string)Dts.Variables["$Project::TargetSite"].Value);
string datatosend = (string)Dts.Variables["User::RequestBody"].Value;
if (datatosend != "")
{
string result;
using (WebClient webClient = new WebClient())
{
webClient.Proxy = new WebProxy(proxyServer, proxyPort); // Connect via the proxy
var bytes = Encoding.UTF8.GetBytes(username + ":" + password);// Build a means to authenticate
var auth = "Basic " + Convert.ToBase64String(bytes);
NetworkCredential myCreds = new NetworkCredential(username, password);
webClient.Credentials = myCreds;
webClient.Headers[HttpRequestHeader.Authorization] = string.Format("Basic ", credentials);
//webClient.Headers[HttpRequestHeader.Authorization] = auth; // Add the authorization header
webClient.Headers[HttpRequestHeader.ContentType] = "text/json"; // Add information about the content
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
try
{
result = webClient.UploadString(TargetSite, datatosend); // Issue the request
}
catch (WebException ex)
{
Dts.Events.FireError(0, "", "UnableToSendData: " + ex.Message.ToString() + ex.StackTrace, string.Empty, 0);
return;
}
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Everything works until the request is issued - that's when I am hit with the 401 error and the response from the Uri is null;
I am at a loss because I am told my public IP is on their permissions list, so not sure why the request fails.
Any assistance would be greatly appreciated.
Many thanks in advance.
Related
I'm trying to retrieve and read emails from my Outlook mail. Unfortunately my mailbox uses Authenticity, which I need to deal with. I have tried a mailbox that does not use Authenticity and the code works. I followed the instructions here https://www.emailarchitect.net/eagetmail/ex/c/22.aspx
(I used the library to read a mailbox that does not use OAuth). So I registered my application on Microsoft Azure as instructed (except for authentication, which was the last step). Unfortunately I get this error System.ComponentModel.Win32Exception
HResult=0x80004005 Message=System cannot find the specified file.
Source=System.Diagnostics.Process
I also tried another library
https://afterlogic.com/mailbee-net/docs/OAuth2MicrosoftRegularAccountsInstalledApps.html
But with the same result
It is larger project, so I will post method where I am getting the error. I will paste more code, if you will need it.
Feel free to ask.
Thanks for any advice.(The documentation is great, so I didn't want to change it)
const string clientID = "Client ID";
const string clientSecret = "client Secret";
const string scope = "https://outlook.office.com/IMAP.AccessAsUser.All%20https://outlook.office.com/POP.AccessAsUser.All%20offline_access%20email%20openid";
const string authUri = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
const string tokenUri = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
static int GetRandomUnusedPort()
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
listener.Stop();
return port;
}
async void DoOauthAndRetrieveEmail()
{
// Creates a redirect URI using an available port on the loopback address.
string redirectUri = string.Format("http://127.0.0.1:{0}/", GetRandomUnusedPort());
Console.WriteLine("redirect URI: " + redirectUri);
// Creates an HttpListener to listen for requests on that redirect URI.
var http = new HttpListener();
http.Prefixes.Add(redirectUri);
Console.WriteLine("Listening ...");
http.Start();
// Creates the OAuth 2.0 authorization request.
string authorizationRequest = string.Format("{0}?response_type=code&scope={1}&redirect_uri={2}&client_id={3}&prompt=login",
authUri,
scope,
Uri.EscapeDataString(redirectUri),
clientID
);
// Opens request in the browser.
//There is issue
System.Diagnostics.Process.Start(authorizationRequest);
// Waits for the OAuth authorization response.
var context = await http.GetContextAsync();
// Brings the Console to Focus.
BringConsoleToFront();
// Sends an HTTP response to the browser.
var response = context.Response;
string responseString = string.Format("<html><head></head><body>Please return to the app and close current window.</body></html>");
var buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
var responseOutput = response.OutputStream;
Task responseTask = responseOutput.WriteAsync(buffer, 0, buffer.Length).ContinueWith((task) =>
{
responseOutput.Close();
http.Stop();
Console.WriteLine("HTTP server stopped.");
});
// Checks for errors.
if (context.Request.QueryString.Get("error") != null)
{
Console.WriteLine(string.Format("OAuth authorization error: {0}.", context.Request.QueryString.Get("error")));
return;
}
if (context.Request.QueryString.Get("code") == null)
{
Console.WriteLine("Malformed authorization response. " + context.Request.QueryString);
return;
}
// extracts the code
var code = context.Request.QueryString.Get("code");
Console.WriteLine("Authorization code: " + code);
string responseText = await RequestAccessToken(code, redirectUri);
Console.WriteLine(responseText);
OAuthResponseParser parser = new OAuthResponseParser();
parser.Load(responseText);
var user = parser.EmailInIdToken;
var accessToken = parser.AccessToken;
Console.WriteLine("User: {0}", user);
Console.WriteLine("AccessToken: {0}", accessToken);
RetrieveMailWithXOAUTH2(user, accessToken);
}
I have a web app running in Azure which has azure Active Directory authentication enabled. This is given below (I have configured this correctly there is no issue with this): -
Now I want to call one of the API of this web app. Code for getting access token based on the client credentials: -
public static string GetAccessToken()
{
string authContextURL = "https://login.microsoftonline.com/" + "TENANT_ID";
var authenticationContext = new AuthenticationContext(authContextURL);
var credential = new ClientCredential("CLIENT_ID", "CLIENT_SECRET");
var result = authenticationContext.AcquireTokenAsync("URL_FOR_MY_WEBAPP", credential).Result;
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the token");
}
string token = result.AccessToken;
return token;
}
Code for calling the desired API: -
private static string GET(string URI, string token)
{
Uri uri = new Uri(string.Format(URI));
// Create the request
var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "GET";
// Get the response
HttpWebResponse httpResponse;
try
{
httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
}
catch (Exception ex)
{
return ex.Message;
}
string result = null;
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}
return result;
}
I am getting an unauthorized error while getting the response. Could anyone tell what is wrong here? The same service principal is working with graph client. Any help or suggestion will be appreciated.
The resource to acquire access token is not correct. You should use the same client id of your AD app.
var result = authenticationContext.AcquireTokenAsync("{CLIENT_ID}", credential).Result;
Is there a way to Http Authentication with WebSocket4Net? I would like to pass credentials to my client. This is what my code looks like:
public bool Connect(string uri, ICredentials credentials = null)
{
if (this.ws == null)
{
try
{
////this.ws = new WebSocket(uri, string.Empty, WebSocketVersion.None, null, );
this.ws = new WebSocket(uri);
this.ws.Opened += this.OnWebSocketOpen;
this.ws.Closed += this.OnWebSocketClose;
this.ws.Error += this.OnWebSocketFail;
this.ws.MessageReceived += this.OnWebSocketMessage;
try
{
this.ws.Open();
return true;
}
catch (Exception ex)
{
Log.Error("Open web socket failed", ex);
this.ws = null;
}
}
catch (Exception exception)
{
throw new CanNotConnectToDeviceException(new Uri(uri, UriKind.Relative), exception);
}
}
return false;
}
I'm not sure that I understand your question clearly, but I still try to help.
Do you mean you're developing a web service, and need "Basic HTTP Authentication"?
If you're doing the server side, and require an authentication, you can response HTTP 401 first.
Most of browser will notify user when it received HTTP 401.
If you're doing the client side, and you want to send authentication automatically,
you can refer to the issue of WebSocket4Net.
Please notice that Basic HTTP Authentication is PLAIN TEXT.
Thanks J.C for the Link. I used it to create a little helper class.
public class HttpHelper : IHttpHelper
{
public KeyValuePair<string, string>
CreateAuthorizationHeader(ICredentials credentials)
{
NetworkCredential networkCredential =
credentials.GetCredential(null, null);
string userName = networkCredential.UserName;
string userPassword = networkCredential.Password;
string authInfo = userName + ":" + userPassword;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
return new KeyValuePair<string, string>("Authorization", "Basic " + authInfo);
}
}
Can someone please take a look at the code below and tell me what I am doing wrong. I am just going in circles,,, any pointers greatly appreciated
public class FtpWebRequestUtil
{
private static string RemoteHost;
private static string RemoteFtpPath;
public static NetworkCredential Credential = new NetworkCredential();
public FtpWebRequestUtil()
{
}
public FtpWebRequestUtil(string RemoteAddress, string RemotePath, string RemoteUser, string RemotePwd)
{
Credential.UserName = RemoteUser;
Credential.Password = RemotePwd;
RemoteHost = RemoteAddress;
RemoteFtpPath = RemotePath;
}
public string UploadFile(string localFilePath)
{
int startTime = Environment.TickCount;
// Console.WriteLine("Uploading File " + localFilePath);
try
{
FileInfo localFile = new FileInfo(localFilePath); //e.g.: c:\\Test.txt
byte[] buf = new byte[2048];
int iWork;
string remoteFile = "ftp://" + RemoteHost + "/" + RemoteFtpPath + "/" + localFile.Name;
FtpWebRequest req = (FtpWebRequest) FtpWebRequest.Create(remoteFile);
// req.Proxy =
req.Credentials = Credential;
// FtpWebRequest req = (FtpWe
req.UseBinary = true;
req.KeepAlive = true;
req.Method = WebRequestMethods.Ftp.UploadFile;
StreamWriter myStreamWriter = new StreamWriter(req.GetRequestStream());
myStreamWriter.Write(new StreamReader("TestFiles\\" + localFile.Name).ReadToEnd());
myStreamWriter.Close();
FtpWebResponse myFtpWebResponse = (FtpWebResponse) req.GetResponse();
Console.WriteLine("Upload File Complete, status: " + myFtpWebResponse.StatusDescription);
myFtpWebResponse.Close();
return "SUCCESS";
}
catch (Exception ex)
{
Console.WriteLine("There was an error connecting to the FTP Server.");
Console.WriteLine(ex.Message);
throw ex;
}
Console.WriteLine("Time taken for downloading file is " + (Environment.TickCount - startTime).ToString());
return "FAILURE";
}
************************ *********************************
FtpWebRequestUtil ftpClient = new FtpWebRequestUtil(FtpUrl, InputFolder, FtpUser, FtpPassword);
try
{
Thread.Sleep(5000);
ftpClient.UploadFile(UploadingFileName);
}
catch (Exception exception)
{
Assert.Fail(exception.Message);
}
finally
{
ftpClient = null;
}
}
}
req.Proxy = new WebProxy(); // initialize this FtpWebRequest property
It turns out that only the RETR, LIST, and NLST methods are supported by System.Net.FtpWebRequest when a HTTP proxy is configured and it doesn't matter that you are not setting a proxy in your code: if a HTTP proxy (not FTP proxy) is configured in the system proxy settings (in i.e. : Internet Options\Connections\LAN setting\Proxy Server\ Use a proxy server for your LAN), then you will get this error when trying to upload to the FTP server.
The workaround is use IE to change the system settings to switch off the use of the HTTP proxy. However if you have access to the affected code the solution is to set the Proxy property of the request to null, for example:
request.Proxy = null;
The exceptions itself is the answer - it is not supported. Probably you have some HTTP proxy that is preventing direct connection to FTP. According to MS documentation, if the specified proxy is an HTTP proxy, only the DownloadFile, ListDirectory, and ListDirectoryDetails commands are supported - so UploadFile is not.
I am trying to get the location of client machine using ip address. Client can access the internet only if
he/she provide the proxy authenication.
Let us say client need to access the 'www.google.com' on the browser then immediately Authenication Required
prompt window open and then client enter his/her username and password. But it is possible the few users does
not required the provide the authenication in order to access internet.
This segment of code does not helped me...
string url = "http://freegeoip.net/xml/";
WebClient wc = new WebClient();
WebProxy proxyObj = new WebProxy("http://freegeoip.net/xml/");
proxyObj.Credentials = CredentialCache.DefaultCredentials;
Uri uri = new Uri(url);
MemoryStream ms = new MemoryStream(wc.DownloadData(uri));
XmlTextReader rdr = new XmlTextReader(url);
XmlDocument doc = new XmlDocument();
ms.Position = 0;
doc.Load(ms);
ms.Dispose();
In the above code if i add network credential instance with username, password and domain then it's work perfectly
Instead of providing the default net credential in code itself, I need to get the username and password from the users(client
machine).
My question is how to prompt the Authentication Required Window and get the username and password to load the download from url
I would be glad if someone throw light on this issue...
Edit: Somehow basic authentication window prompt and now i can get the username and password which can use for credential
try
{
var reg = HttpContext.Current.Request;
if (!String.IsNullOrEmpty(reg.Headers["Authorization"]))
{
var cred = System.Text.ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(Request.Headers["Authorization"].Substring(6))).Split(':');
var user = new { Name = cred[0], Pass = cred[1] };
string url = "http://freegeoip.net/xml/";
WebClient wc = new WebClient();
WebProxy wProxy = new WebProxy();
ICredentials crd;
crd = new NetworkCredential("'" + cred[0] + "'", "'" + cred[1] + "'");
wProxy = new WebProxy("myproxy", true, null, crd);
wc.Proxy = wProxy;
Uri uri = new Uri(url);
string content = wc.DownloadString(uri);
}
else
{
try
{
//var reg = HttpContext.Current.Request;
if (String.IsNullOrEmpty(reg.Headers["Authorization"]))
{
var res = HttpContext.Current.Response;
res.StatusCode = 401;
res.AddHeader("WWW-Authenticate", "Basic realm = \"freegeoip\"");
//res.End();
}
}
catch (Exception ex)
{
}
}
}
catch(Exception ex)
{
}
But Still It throwing the "Unable to connect to the remote server"