Apache Commons HttpClient with user authentication - apache

Need to do an HTTP GET with user ID and password authentication using the Apache Commons HttpClient:
val targetHost = new HttpHost("url", 8080, "http");
val credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("user", "password"));
val authCache = new BasicAuthCache();
authCache.put(targetHost, new BasicScheme());
val context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
val client = HttpClientBuilder.create().build();
var response = client.execute(new HttpGet("url"), context);
var statusCode = response.getStatusLine().getStatusCode();
But it's not able to fetch the data from the URL as it is failing to connect to the URL. Can someone assist?

Check the parameters to HTTPHost. I'm pretty sure that you don't intend to connect to a server named url.

Related

Getting an OAuth2 authentication token in VB.net

I'm trying to get an OAuth token using a ClientID and SecretID.
My code so far:
Dim clientId As String = "8cd6b80dd822961f362"
Dim clientSecret As String = "5afbd4bb280f29cba5ec1f362"
Dim credentials = String.Format("{0}:{1}", clientId, clientSecret)
Dim headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials))
Dim content = New FormUrlEncodedContent(New Dictionary(Of String, String) From {
{"client_id", clientId},
{"client_secret", clientSecret},
{"response_type", "code"},
{"redirect_uri", "https://somesite.com/"},
{"grant_type", "authorization_code"}})
Dim requestMessage = New HttpRequestMessage(HttpMethod.Post, "https://api.site.com/oauth2/authorize")
requestMessage.Headers.Authorization = New AuthenticationHeaderValue("Basic", headerValue)
requestMessage.Content = content
Dim client As HttpClient = New HttpClient()
Dim task = client.SendAsync(requestMessage)
Dim response = task.Result
response.EnsureSuccessStatusCode()
Dim responseBody As String = response.Content.ReadAsStringAsync().Result
MsgBox(responseBody)
The above code returns the HTML for the redirect_uri site and not a token.
What am I missing or doing wrong?
Using Postman and the credentials provided I managed to get the token.
The second step of a code flow uses the token endpoint, not the authorize endpoint. Your payload looks correct though. Try posting it to this endpoint:
https://api.site.com/oauth2/token
By default HttpClient is using AllowAutoRedirect = true. The documentation says:
The Authorization header is cleared on auto-redirects and the handler automatically tries to re-authenticate to the redirected location. No other headers are cleared. In practice, this means that an application can't put custom authentication information into the Authorization header if it is possible to encounter redirection.
So depending on the setup of the server you might have to create a CookieContainer and do the redirecting on your own.
Update:
The usage of a certificate store is something I didn't get from your question. If you want to do similar handling of certificates like browsers do you have to implement this feature yourself. Here is a C# example of how you can extend WebClient class with a dedicated CookieContainer and X509 certificate handling. I used it with smart card reader. It should work similar in vb.net. Hope it helps to find the right .Net classes and how to put things together:
public class SmartCardClient : WebClient
{
public CookieContainer Cookies = new CookieContainer();
public Uri LastResponseUri = null;
public X509Certificate2 cert = null;
private string IssuerName = null;
public SmartCardClient(string issuerName)
{
IssuerName = issuerName;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
SelectCertificate();
}
protected override WebRequest GetWebRequest(Uri uri)
{
var request = base.GetWebRequest(uri) as HttpWebRequest;
LastResponseUri = null;
if (request != null)
{
request.CookieContainer = Cookies;
request.UseDefaultCredentials = true;
request.AllowAutoRedirect = true;
}
return request;
}
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse response = base.GetWebResponse(request);
LastResponseUri = response.ResponseUri;
return response;
}
public void SelectCertificate()
{
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certs = (X509Certificate2Collection)store.Certificates
.Find(X509FindType.FindByTimeValid, DateTime.Now, false)
.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, false)
.Find(X509FindType.FindByIssuerName, IssuerName, false);
if (certs.Count > 1)
certs = X509Certificate2UI.SelectFromCollection(
certs, "Select Certificate", "Please select a certificate:",
X509SelectionFlag.MultiSelection
);
if (certs.Count > 0)
cert = certs[0];
store.Close();
}
}

How to use WebProxy with RestSharp?

I would like to know how to use WebProxy with RestSharp. I am using version 108.0.1 and the code given below returns 407 when running locally from my workstation, which should use my credentials.
var client = new RestClient("https://www.google.com");
var proxy = new System.Net.WebProxy("http://mycorpproxy.com");
proxy.UseDefaultCredentials = true;
client.Options.Proxy = proxy;
var request = new RestRequest();
request.Method = Method.Get;
var response = client.Execute(request);
You need to specify the proxy in the options when you create the client, not after. In v107, the options object properties were init-only, but it fails on legacy SDKs, so we had to revert it to setters, but setting the options that are used to create an HttpClient instance after the client is created has no effect.
var proxy = new WebProxy("http://mycorpproxy.com") {
UseDefaultCredentials = true
};
var options = new RestClientOptions("https://www.google.com") {
Proxy = proxy
};
var client = new RestClient(options);

How do I authenticate OneDrive for Business with Service to Service oauth2 authentication?

The tutorial for OneDrive for Business (here: https://dev.onedrive.com/auth/aad_oauth.htm)
However, I don't want the user to have to login as I'm building a web API - I want the app to login. So, I have followed the tutorial for service to service authentication (here: https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx) which gets me an access token.
However, when I try to authenticate with the service I get an error saying "unsupported app only token". The code I'm using is below (btw, I'm using RestSharp):
public string GetAccessToken()
{
var client = new RestClient("https://login.microsoftonline.com/<tenant>/oauth2");
var request = new RestRequest("token", Method.POST);
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("client_id", <client_id>);
request.AddParameter("client_secret", <client_secert);
request.AddParameter("resource", "https://<tenant>-my.sharepoint.com/");
var response = client.Execute(request);
var content = response.Content;
var authModel = JsonConvert.DeserializeObject<AuthResponseModel>(content);
return authModel.AccessToken;
}
this gets me the access token
This is how I try to access my drive:
public string GetDrive()
{
var accessToken = GetAccessToken();
var client = new RestClient("https://<tenant>-my.sharepoint.com/_api/v2.0/");
var request = new RestRequest("drive", Method.GET);
request.AddHeader("Authorization: Bearer", accessToken);
var response = client.Execute(request);
var content = response.Content;
return content;
}
Does anyone have any tips? This is getting slightly maddening.

OAuth2 grant_type missing

I am getting error that required parameter grant_type is missing in the request.
Using OAuth2 for Webserver application.
Please see below the code:
var httpClient : HTTPClient = new HTTPClient();
httpClient.setTimeout(3500);
httpClient.setRequestHeader("ContentType", "application/x-www-form-urlencoded");
httpClient.open("POST", "https://accounts.google.com/o/oauth2/token");
var param1:String = "code="+Encoding.toURI(pdict.CurrentHttpParameterMap.code.value.split('.')[0]);
var param2:String = "client_id="+pdict.session.custom.client_id;
var param3:String = "client_secret="+pdict.session.custom.client_secret;
var param4:String = "redirect_uri="+Encoding.toURI(pdict.session.custom.redirect_uri);
var param5:String = "scope=";
var param6:String = "grant_type=authorization_code";
Using below syntax i.e. passing variables as part of Request body solved it.
var client_secret : HTTPRequestPart = new HTTPRequestPart("client_secret", pdict.session.custom.client_secret);

Use both premitive and proxy authentication for a apache HttpClient 4.3.1

I am trying to connect a target host, which requires a username and password for primitive authentication from a proxy server that also have its own host, username and password.
Updated
The use case is something like this
My System connects with internet using proxy assume proxy.mydomain.com
And my proxy uses authentication to connect and authenticatuion is done using username and password
Username : MyDomain\myusername
Password : Password
Ok now the API or service which I want to connect is using Preemptive authentication I have some code snippet form API Docs :
final HttpState state = client.getState();
final HttpClientParams params = client.getParams();
myCreds = new UsernamePasswordCredentials(userName, userPassword);
System.out.println("Created credentials for " + myCreds.getUserName());
// Apply the credentials to the httpclient for preemptive authentication.
params.setAuthenticationPreemptive(true);
state.setCredentials(AuthScope.ANY, myCreds);
I tried with all apche clients from 4.1 to 4.3 but no solution at all.
I can set one credential but not getting how can both set together to a HttpClient ?
Below is my Code :
CloseableHttpResponse response;
HttpHost myHost=new HttpHost("172.17.8.192", 443, "https");
CredentialsProvider myServerCredsProvider;
if (userName.length() > 0 && userPassword.length() > 0)
{
myServerCredsProvider = new BasicCredentialsProvider();
myServerCredentials = new UsernamePasswordCredentials(userName, userPassword);
logger.info("Username : "+userName+" Password : "+userPassword);
myServerCredsProvider.setCredentials(
new AuthScope(myHost.getHostName(),myHost.getPort()),
myServerCredentials);
logger.info("After Creds Provider");
client = HttpClients.custom()
.setDefaultCredentialsProvider(myServerCredsProvider).build();
}
HttpHost proxy = new HttpHost("proxy.mycompany.com", 8080);
UsernamePasswordCredentials poxyAuthDetails=new UsernamePasswordCredentials("MyDomain//username", "password");
CredentialsProvider proxyProvider=new BasicCredentialsProvider();
proxyProvider.setCredentials(new AuthScope(proxy.getHostName(),proxy.getPort()), poxyAuthDetails);
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
HttpGet getServerDetailsUrl=new HttpGet(BaseURI+DominoServerAddress+API_BASE_URI);
getServerDetailsUrl.setConfig(config);
try {
response=client.execute(getServerDetailsUrl);
try {
HttpEntity entity = response.getEntity();
logger.info("----------------------------------------");
logger.info(response.getStatusLine());
if (entity != null) {
logger.info("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} catch (IOException ex) {
isAuthenticate=false;
logger.info("Exception Occured "+ex.getMessage());
}
I am getting exception while trying to execute :
HTTP/1.1 407 Proxy Authorization Required