I'm building a Java application to extract files from Sharepoint using Sharepoint's REST api. First I need to authenticate, our organisation uses OKTA to obtain a token.
The example code I'm using is:
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new NTCredentials(user, pwd, "", ""));
HttpHost target = new HttpHost("organisation.sharepoint.com", 80, "http");
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
// The authentication is NTLM.
// To trigger it, we send a minimal http request
HttpHead request1 = new HttpHead("/");
CloseableHttpResponse response1 = null;
try {
response1 = httpclient.execute(target, request1, context);
EntityUtils.consume(response1.getEntity());
System.out.println("1 : " + response1.getStatusLine().getStatusCode());
I need to modify the NTLM code to use Okta instead to make the call to Sharepoint with context set.
Any help appreciated!
Unfortunately, this is not achievable at the moment. This feature has been requested and will be reviewed by engineering. However, it is not actively being worked on as of right now.
Related
I was happy to access SharePoint using PowerShell. It just picked -DefaultCredential and I didn't have to worry about that. That was for prototyping.
But my actual code is Java. Now I am not sure about this at all.
Even though I make REST calls, even SOAP would fail if I don't authenticate properly.
Method 1 : NTLM
Here the only thing I am not sure about is the workstation ID. I login using Citrix to a VM and there is an explicit Workstation ID. I use that.
Returns 401.
DefaultHttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://teams.host.com/_vti_bin/listdata.svc/");
NTCredentials credentials = new NTCredentials("user", 'pass', "workstation", "Domain");
client.getCredentialsProvider().setCredentials(new AuthScope("teams.host.com",80), credentials);
HttpResponse response = client.execute(request);
Method 2 : Basic authentication.
HttpGet request = new HttpGet("http://teams.host.com/_vti_bin/listdata.svc/");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("user", "password"));
CloseableHttpClient httpClient =
HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider).build();
HttpResponse response = httpClient.execute(request);
Returns 401.
What other method do I use ? Digest ? Since I don't know how -DefaultCredential in PowerShell worked I am back to the drawing board.
How should I investigate this ? I must be making some basic mistakes in this Java code. The flow is not right. That is my supposition.
So from Apache HttpClient this is the code that connects to SharePoint 2010. The workstation ID is the one used when I use Citrix XenDesktop to login to a Windows machine. I am able to get the result of my REST Get request.
This uses NTLM authentication.
DefaultHttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://teams.host.com/_vti_bin/listdata.svc/");
NTCredentials credentials = new NTCredentials("user", 'pass', "workstation", "Domain");
client.getCredentialsProvider().setCredentials(new AuthScope("teams.host.com",80), credentials);
HttpResponse response = client.execute(request);
I've tried to connect to our SharePoint and POST some data to a list.
A user can interact with a Web-App and send some Information. These data will be send to a Java-Web-Interface running on a tomcat. The Java-Code should connect to our SharePoint and post the data in the list. Today, I read a lot of tutorials and ressources on the web... Most of them are deprecated ore discuss lightly different situations! SO! My mind whispered: "Go on and visit stackoverflow." And here I am, asking this question:
The Situation is described above. I call a web-Interface vie JS (angularJS) and pass an E-Mail-Adress which the user enters in the front-end. Here it goes in:
#Path("webservice")
public class SetEmail {
#POST
#Path("/SetEmail")
#Consumes(MediaType.APPLICATION_JSON + ";charset=UTF-8")
#Produces("text/plain")
public String addItem(String incoming) throws ClientProtocolException, IOException, AuthenticationException{
String result = "error";
JSONObject jsonObj = new JSONObject(incoming);
String listName = "Leads";
String username = "...";
char[] password= new char[]{'...', '...', ...};
String website = "...";
Now, after all I read, I have to get the DigestValue from SharePoint, because I want to make a POST-Request:
//Get the Digestvalue.
CredentialsProvider provider = new BasicCredentialsProvider();
provider.setCredentials(AuthScope.ANY, new NTCredentials(username, password.toString(), "http://...", "https://..."));
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();
HttpPost httpPost = new HttpPost(website + "_api/contextinfo");
httpPost.addHeader("Accept", "application/json;odata=verbose");
httpPost.addHeader("content-type", "application/json;odata=verbose");
httpPost.addHeader("X-ClientService-ClientTag", "SDK-JAVA");
HttpResponse response = client.execute(httpPost);
byte[] content = EntityUtils.toByteArray(response.getEntity());
String jsonString = new String(content, "UTF-8");
System.out.println(response);
JSONObject json = new JSONObject(jsonString);
String FormDigestValue = json.getJSONObject("d").getJSONObject("GetContextWebInformation").getString("FormDigestValue");
After getting the Digest, I am able to execute the actual request:
//POST the data.
CloseableHttpClient client2 = HttpClients.createDefault();
HttpPost httpPost2 = new HttpPost(website + "_api/web/lists/GetByTitle(" + listName + ")");
httpPost2.setEntity(new StringEntity("test post"));
NTCredentials creds = new NTCredentials(username, password.toString(), "http://...", "https://...");
httpPost2.addHeader(new BasicScheme().authenticate(creds, httpPost2, null));
httpPost2.addHeader("X-RequestDigest", FormDigestValue);
httpPost2.addHeader("Accept", "application/json;odata=verbose");
httpPost2.addHeader("Content-Type", "application/json;odata=verbose");
CloseableHttpResponse response2 = client2.execute(httpPost2);
System.out.println(response2);
client2.close();
}
}
I know this isn't the most beautiful Code and yes, I am not an Java expert. My Problems are:
I don't know weather all of these code-Fragments are up to date or
weather I am using deprecated ones. Perhaps someone is able to
enlighten me.
I am using HttpClient from Apache. To me it looked like the most
usable library. Is that right?
Everytime I execute the Action on the front-end and my Code starts
running, I am getting an HTTP 401 Unauthorized error. I tried
various Kinds of Code but none worked well.
HttpResponseProxy{HTTP/1.1 401 Unauthorized [Server: Microsoft-IIS/8.0, SPR..
Perhaps someone has the Patience to tell me how to do it. Thank you.
Whoa... you are really trying some black magic here ;) - I would suggest you to get your HTTP POST / GET in a tool like Postman or some other REST tool working and then return to your code.
I don't know exactly what you are trying to achieve, but it might be easier to go via powershell (if you are trying to create a migration script) or JavaScript (if you are on a website).
Be aware that authentication differs in SharePoint online and SharePoint on premise... this is also customizable by your company (you can for example implement forms-based auth as well). Be sure to know what YOUR SharePoint is using. (Or share some more info, so we can help)
I've just upgraded to org.apache.httpcomponents.httpclient 4.3. Previously I created a client and did pre-emptive authentication like this:
final HttpClient client = new DefaultHttpClient();
final HttpRequestBase request = new HttpGet(url);
request.addHeader(BasicScheme.authenticate( new UsernamePasswordCredentials(username,password), "UTF-8", false));
Now that this is deprecated I have to create a client and authenticate like this:
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
clientBuilder = clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
However instead of authenticating and making a successful GET I get a 302 in response. I think this could be fixed by setting pre-emptive authentication, but I can't find how. Maybe I have authentication in this second example all wrong?
Can I get some pointers, please?
It's not clear whether this is actually a real problem.
HTTP 302 is a redirection. You need to follow the redirect.
I know the default password for 5.9.0's HawtIO/Jolokia is set in the \conf\ folder and is
admin/admin
system/manager
etc
However, none of those password are working when trying to execute the restful commands through Java:
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(null, -80), new UsernamePasswordCredentials("admin", "admin"));
CloseableHttpClient httpclient0 = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
URI uri0 = URI.create("http://localhost:8161/hawtio/auth/login/");
HttpGet httpget = new HttpGet(uri0);
HttpResponse r0 = httpclient0.execute(httpget);
System.out.println("Login form get: " + r0.getStatusLine());
for (Header h : r0.getAllHeaders())
System.out.println(h.getName() + "/" + h.getValue());
HttpEntity entity = r0.getEntity();
InputStream is0 = entity.getContent();
String resp = IOUtils.toString(is0);
System.out.println("Response0: " + resp);
The following code just spits back a 403 Forbidden reply! I've tried many combinations of username and passwords.
Login form get: HTTP/1.1 403 Forbidden
Access-Control-Allow-Origin/*
Content-Length/0
Server/Jetty(7.6.9.v20130131)
What works here?
I recall when running 5.8.0 that "admin/admin" worked, but I'd like to use 5.9.0 instead. It would be lame to back out of this version just because the username and password changed.
Further, which \conf file dictates this password...?
you've almost got it, you just need to POST to that URL instead of doing a GET. And you just set your username/password in the Authorization header. The authentication filter in hawtio avoids sending back a 401 as that makes the browser authentication prompt appear, hence why you don't see 401 returned instead.
Two related questions, I'm using Apache HTTP Client 4.x API. myHttpPost is an instance of HttpPost and myHttpClient is an instance of HttpClient. I'm trying to send a request using basic authentication. So I have a HttpClient and create a HttpPost.
The 'brute force' way of setting a basic authentication header seems to be to set it in the HttpPost header.
String encoding = Base64Encoder.encode("username" + ":" + "password");
myHttpPost.setHeader("Authorization", "Basic " + encoding);
The example above came from another stack overflow question (can't find link to it now). In relation to the Base64Encoder class - which package would I find it in or where would I download it from?
Main question - I was hoping to do basic authentication in a more aesthetic manner using the code below:
myHttpClient.getCredentialsProvider().setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthPolicy.BASIC),
new UsernamePasswordCredentials("username", "password")
);
But this doesn't seem to work. So is the first example above the right way to do basic authentication with Apache HTTP Client 4.0? Or is there a cleaner/simpler way.
In relation to the Base64Encoder class - which package would I find it
in or where would I download it from?
Base64Encoder can come from various places, I couldn't find something that matches with your static encode method.
As for Credentials, you need to set scheme to Basic on your AuthScope, like so:
myHttpClient.getCredentialsProvider().setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, "basic"),
new UsernamePasswordCredentials("username", "password")
);
or
myHttpClient.getCredentialsProvider().setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthPolicy.BASIC),
new UsernamePasswordCredentials("username", "password")
);
I know this is a really old post. But, just wanted to answer so that others will benefit in future:
If you are using a username which is to be represented using Variable width encoding (http://en.wikipedia.org/wiki/Variable-width_encoding), then make sure that you change the encoding used to form the bytes for (username:password) as follows:
HttpParams params = new BasicHttpParams();
params.setParameter(AuthPNames.CREDENTIAL_CHARSET, HTTP.UTF_8);
By default, the encoding used is HttpProtocolParams.HTTP_ELEMENT_CHARSET.
HttpClient does not attempt to authenticate with the origin or proxy server unless explicitly challenged. I suspect you would like HttpClient to authenticate preemptively. While the preemptive authentication is disabled per default (and I personally would discourage its application outside secure or internal networks) one can force the preemptive authentication using example below
http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientPreemptiveBasicAuthentication.java
I tried out the solution suggested in http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientPreemptiveBasicAuthentication.java and it works for Base64 Encoding Basic Authentication.
I guess the
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local
// auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(target, basicAuth);
// Add AuthCache to the execution context
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
makes the miracle :)
as without this i always receive "401 Unauthorized" HTTP response