I am trying to connect to a web service from Lockheed Martin located here. I have looked at other examples and am using the following code to try and establish a connection. All I want to know at this point is if I have established a connection and been authorized but I repeatedly get an exception saying
Unauthorized at System.Net.HttpWebRequest.GetResponse()
. Am I setting up the web request and response correctly? Is there a different method that would simply let me know if I've successfully connected?
try
{
//Connect to the Lockheed Martin web client
WebRequest client = WebRequest.Create("https://www.elabs.testafss.net/Website2/ws");
string username = "username";
string password = "password";
string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(username + ":" + password));
client.Headers.Add("Authorization", "Basic " + credentials);
WebResponse response = client.GetResponse();
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Probably your user / password is incorrect, looking at the documentation of the web service, your code is reproducing the exactly same hash that is in following sample:
Authentication - Basic Auth
Authentication is performed using the Basic Auth protocol. An authorization header is supplied with every web service request. This is sometimes called pre-emptive authentication. The header looks like this:
Authorization: Basic Vendor_ID:Vendor_Password
where the Vendor_ID:Vendor_Password string is converted to Base64.
Example
Authorization: Basic JoesFlightServices:SecretPW
Converted to Base64:
Authorization: Basic Sm9lc0ZsaWdodFNlcnZpY2VzOlNlY3JldFBX
Note that conversion to Base64 does not ensure the information will be private. We use HTTPS to encrypt the entire HTTP message including the headers.
Source
Related
I am able generate access token with docusign site by using link https://developers.docusign.com/oauth-token-generator
But when try to get access token in our system using c# code then getting message (The remote server returned an error: (400) Bad Request.)
I follow the authenticate process mentioned in below link.
https://developers.docusign.com/esign-rest-api/guides/authentication/oauth2-code-grant
I able to get authentication code. I used this authentication code to hit API (https://account-d.docusign.com/oauth/token).
Below is my code sample
string integrationKey = "key removed";
string secretKey = "key removed";
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://account-d.docusign.com/oauth/token");
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
string apiStoreConsumer = "removed";
httpWebRequest.Headers.Add("Authorization", "Basic " + apiStoreConsumer);
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string input = "authorization_code&authorization_code= <authentication code goes here>;
streamWriter.Write(input);
streamWriter.Flush();
streamWriter.Close();
}
WebResponse response = (HttpWebResponse)httpWebRequest.GetResponse();
Query:
Why am I getting 400 error?
Do we have any expiry time for access token, if yes then how long?
Does authentication code get change for every request?
Please help me on this.
Thank You!
I recommend you use a library for OAuth in .NET/C#.
If you want to see how this is done, please clone this repo.
The issue is that you need to first get a code and then exchange it for a token. There are 2 steps involved if you do this manually.
The first step requires you to authenticate the user in a browser before you can call any API.
During that step you need to pass in your integration key and redirect back to your URL.
Once redirected back you'll receive a code that can be exchanged for an access token using the API call you had talks about.
My WPF desktop application (C#) is attempting to read the user's Outlook emails through the Microsoft Graph API. I am stuck in the authentication process; I've already received an authentication code and now I'm trying to get an access token from Azure but keep getting a HTTP 400 error code when sending out the request for the access token:
/**** Auth Code Retrieval ****/
string authCodeUrl = "https://login.microsoftonline.com/common/oauth2/authorize";
authCodeUrl += "?client_id" = clientId;
authCodeUrl += "&redirect_uri=" + redirectUri;
authCodeUrl += "&response_type=code";
authCodeUrl += "&resource=https%3A%2F%2Fgraph.microsoft.com%2F";
Process.start(authUrl); // User logs in, we get the auth code after login
string code = "......"; // Hidden for this post
/**** Access Token Retrieval ****/
string tokenUrl = "https://login.microsoftonline.com/common/oauth2/token"
string content = "grant_type=authorization_code";
content += "&client_id=" + clientId;
content += "&resource=https%3A%2F%2Fgraph.microsoft.com%2F";
content += "&code=" + code;
content += "&redirect_uri=" + redirectUri;
WebRequest request = WebRequest.Create(tokenUrl);
request.ContentType = "application/x-www-form-urlencoded";
byte[] data = Encoding.UTF8.GetBytes(content);
request.ContentLength = data.Length;
request.Method = "POST";
try
{
using (Stream stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
WebResponse response = request.GetResponse(); // This throws exception
}
catch (Exception error) // This catches the exception
{
Console.WriteLine(error.Message); // Outputs 400, bad request
}
The above is the code used to retrieve the auth code followed by the attempt to retrieve the access token. We do not have a client_secret because secrets are only for Web applications and this is a native desktop WPF application. I have read that this isn't an issue though. I have followed many tutorials and official docs online, mainly the official Graph authorization doc and I still cannot figure out what I am doing wrong. Any help would be greatly appreciated, thank you.
I used fiddler to debug the request and I found the full error message: The user or administrator has not consented to use the application. I googled this message for a bit and found some stack articles and github issue threads that lead me to the solution: my request had been using "common", in the base URL, as the tenant ID when actually I needed to use my Azure tenant ID which I acquired through this answer on stack. My new base URL for the authentication requests now looks like:
https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/authorize
where "xxxx-....xxx" would be replaced by your Azure tenant id!
If you don't use a client secret, then you need to configure your tenant to support implicit grant flow. You can follow the directions from this blog post to perform / validate the configuration. This requires using the Azure management portal to download, modify the app manifest, and upload it.
Alternatively, and possibly a better strategy, is to switch your code over to using the converged v2.0 authentication endpoints. It allows management of your application using the new app registration portal and nicely supports implicit flow and dynamic scopes. You can find more information about the actual authentication flow here. It isn't far from what you are doing now and requires only a few small tweaks.
If you are still having issues after this, please reach out again. A fiddler / network trace would be very helpful. Also, the detailed message inside the exception would also be very helpful.
I have developed a C# desktop application which makes HTTPS requests to the customers' servers (usually Documentum/SharePoint/Alfresco/NemakiWare/etc HTTPS-based servers).
Several customers have asked us to support their servers which are protected by CA SSO (new name of Siteminder).
QUESTION: What do I need to do to allow my application to send HTTPS requests (and receive responses) with CA SSO-protected servers?
I have developed NTLM-SSO support for our C# desktop application and it works well, but I am not sure about how to proceed for CA SSO.
I have asked the same question on the CA forum, but like most questions there it remains unanswered.
To authenticate with CA SSO and then connect to the desired URL we need to access a protected resource on a web server configured to use CA SSO authentication:
Requests a resource on the server, using an HTTP request.
The request is received by the web server and is intercepted by the CA SSO web agent.
The web agent determines whether or not the resource is protected, and if so, gathers the user’s credentials and passes them to the Policy server.
The Policy server authenticates the user and verifies whether or not the authenticated user is authorized for the requested resource, based on rules and policies contained in the Policy store.
After the user is authenticated and authorized, the Policy server grants access to the protected resources.
This is accomplished with the following steps:
Open a connection (HTTP request in this case) to the URI of the protected resource. Since the request has not yet been authenticated, the CA SSO agent will issue a redirect to a login page. In the code, AllowAutoRedirect is set to false. This is important as the redirect URL will be required for the subsequent POST of login data in step 3 below. If AllowAutoRedirect were True, the response would not include a Location header and the subsequent POST would be made to the original URL, which would then redirect to the login page again. However, a POST occurs between a client and the server, any POST data carried in the payload of the request of step 3 will be lost during the redirect.
Dim request As HttpWebRequest
Dim response As HttpWebResponse
Dim url As String = PROTECTED_URL
request = WebRequest.Create(url)
request.AllowAutoRedirect = False
response = request.GetResponse
' make sure we have a valid response
If response.StatusCode <> HttpStatusCode.Found Then
Throw New InvalidProgramException
End If
' get the login page
url = response.Headers("Location")
request = WebRequest.Create(url)
request.AllowAutoRedirect = False
response = request.GetResponse
The next step involves creating an HTTPS request that POSTs all the form data, including userid and password, back to the server. The purpose of an authentication agent is to verify a user’s identity by validating their userid and password. Thus, their URLs naturally use SSL (secure sockets layer) and are encrypted for us, so we do not required further encryption in our program. However, the formatting of the POST data is interesting in as much as there are two alternatives. The sample program uses the simpler approach of setting the content type to application/x-www-form-urlencoded. Here the POST data is formatted similar to a query string and sent as part of the next request.
Dim postData As String
postData = ""
For Each inputName As String In tags.Keys
If inputName.Substring(0, 2).ToLower = "sm" Then
postData &= inputName & "=" & _
HttpUtility.UrlEncode(tags(inputName)) & "&"
End If
Next
postData += "postpreservationdata=&"
postData += "USER=" + HttpUtility.UrlEncode(USERNAME) & "&"
postData += "PASSWORD=" + HttpUtility.UrlEncode(PASSWORD)
request = WebRequest.Create(url)
cookies = New CookieContainer
request.CookieContainer = cookies
request.ContentType = FORM_CONTENT_TYPE
request.ContentLength = postData.Length
request.Method = POST_METHOD
request.AllowAutoRedirect = False ' Important
Dim sw As StreamWriter = New StreamWriter(request.GetRequestStream())
sw.Write(postData)
sw.Flush()
sw.Close()
response = request.GetResponse
Same idea as Mohit's answer, but it can be done with a much simpler code:
//Make initial request for SM to give you some cookies and the authentication URI
RestClient client = new RestClient("http://theResourceDomain/myApp");
client.CookieContainer = new CookieContainer();
IRestResponse response = client.Get(new RestRequest("someProduct/orders"));
//Now add credentials.
client.Authenticator = new HttpBasicAuthenticator("username", "password");
//Get resource from the SiteMinder URI which will redirect back to the API URI upon authentication.
response = client.Get(new RestRequest(response.ResponseUri));
Although this uses RestSharp, it can be easily replicated using HttpClient or even HttpWebRequest.
My app communicates with an internal web API that requires authentication.
When I send the request I get the 401 challenge as expected, the handshake occurs, the authenticated request is re-sent and everything continues fine.
However, I know that the auth is required. Why do I have to wait for the challenge? Can I force the request to send the credentials in the first request?
My request generation is like this:
private static HttpWebRequest BuildRequest(string url, string methodType)
{
var request = HttpWebRequest.CreateHttp(url);
request.PreAuthenticate = true;
request.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
request.Credentials = CredentialCache.DefaultNetworkCredentials;
request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
request.ContentType = CONTENT_TYPE;
request.Method = methodType;
request.UserAgent = BuildUserAgent();
return request;
}
Even with this code, the auth header isn't included in the initial request.
I know how to include the auth info with basic.... what I want to do is to use Windows Auth of the user executing the app (so I can't store the password in a config file).
UPDATE I also tried using a HttpClient and its own .Credentials property with the same result: no auth header is added to the initial request.
The only way I could get the auth header in was to hack it in manually using basic authentication (which won't fly for this use-case)
Ntlm is a challenge/response based authentication protocol. You need to make the first request so that the server can issue the challenge then in the subsequent request the client sends the response to the challenge. The server then verifies this response with the domain controller by giving it the challenge and the response that the client sent.
Without knowing the challenge you can't send the response which is why 2 requests are needed.
Basic authentication is password based so you can short circuit this by sending the credentials with the first request but in my experience this can be a problem for some servers to handle.
More details available here:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa378749(v=vs.85).aspx
I'm not 100% sure, but I suspect that there is no way around this; it's simply the way HttpWebRequest works.
In the online .NET source, function DoSubmitRequestProcessing which is here, you can see this comment just after the start of the function, line 1731:
// We have a response of some sort, see if we need to resubmit
// it do to authentication, redirection or something
// else, then handle clearing out state and draining out old response.
A little further down (line 1795) (some lines removed for brevity)
if (resubmit)
{
if (CacheProtocol != null && _HttpResponse != null) CacheProtocol.Reset();
ClearRequestForResubmit(ntlmFollowupRequest);
...
}
And in ClearRequestForResubmit line 5891:
// We're uploading and need to resubmit for Authentication or Redirect.
and then (Line 5923):
// The second NTLM request is required to use the same connection, don't close it
if (ntlmFollowupRequest) {....}
To my (admittedly n00bish) eyes these comments seem to indicate that the developers decided to follow the "standard" challenge-response protocol for NTML/Kerberos and not include any way of sending authentication headers up-front.
Setting PreAuthenticate is what you want, which you are doing. The very first request will still do the handshake but for subsequent requests it will automatically send the credentials (based on the URL being used). You can read up on it here: http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.preauthenticate(v=vs.110).aspx.
Alright, so I've seen this question asked but yet have found a simple answer that works.
A user comes to my website and has already "authorized" my website/app using the standard facebook login dialog - USING oauth.
Upon returning to my site the user has a cookie on his machine that starts with "fbsr_%" - from what I'm reading this is considered "the code".
What I'd like to do now is grab this cookie server-side, make a call to facebook, from what I found I'm supposed to call: "https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}"
then receive back the accesstoken...
I would like to receive the access token without having to redirect the user on the client. So what I have so far is as follows, and from what I've gathered it is supposed to work, but for me it always gives me a an error "The remote server returned an error: (400) Bad Request."
string url = "https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}";
string redirectUri = "http://www.mysite.com/";
string code = Request.Cookies["fbsr_" + clientId].Value;
WebRequest request = WebRequest.Create(string.Format(url, clientId, redirectUri, clientSecret, code));
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader streamReader = new StreamReader(stream, encode);
string accessToken = streamReader.ReadToEnd().Replace("access_token=", "");
streamReader.Close();
response.Close();
Any help would be greatly appreciated
Now that Facebook require SSL for applications your "redirect_uri" need to be https (i.e https://apps.facebook.com/myapp/), otherwhise you will get "Bad Request".
The "redirect_uri" for the access_token (https://graph.facebook.com/oauth/access_token) needs to be the same as that when requesting the code that requires the user to login and connect to your app (https://graph.facebook.com/oauth/authorize or https://www.facebook.com/dialog/oauth) or you will get the same error, "Bad Request".
check this tutorial:
http://amirrajan.net/Blog/asp-mvc-and-facebook-single-sign-on