1

I'm trying to connect Sharepoint online REST API using Java. Retrieved cookies -rtfa and fedAuth. Also got xForm Digest value and trying to authenticate. But it always throws Authentication error.

private void getSharePointContents(String rtFa, String fedAuth, String XRequestDigest,String sharePointServerUrl) {
    DefaultHttpClient httpClient = new DefaultHttpClient();

    try {
        HttpGet getRequest = new HttpGet(sharePointServerUrl);
        System.out.println("rtfa :"+ rtFa + "\n , FedAuth: " +fedAuth + "\n XRequestDigest: "+XRequestDigest);
        getRequest.addHeader("Cookie", "rtFa="+rtFa+";FedAuth="+fedAuth);
        getRequest.addHeader("Authorization", "Bearer"+XRequestDigest);
        getRequest.addHeader("accept", "application/json");

        HttpResponse response = httpClient.execute(getRequest);

        if (response.getStatusLine().getStatusCode() == 200) {               
            BufferedReader br = new BufferedReader(
                    new InputStreamReader((response.getEntity().getContent())));
            String output;
            while ((output = br.readLine()) != null) {
                System.out.println(output);
            }
        }else{
            System.out.println(response.getStatusLine().getStatusCode());
            throw new RuntimeException("Failed : HTTP error code : "
                    + response.getStatusLine().getStatusCode());
        }

    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        httpClient.getConnectionManager().shutdown();
    }

This is the error i'm getting:

Apr 03, 2018 3:59:46 PM org.apache.http.impl.client.DefaultRequestDirector handleResponse WARNING: Authentication error: Unable to respond to any of these challenges: {bearer=WWW-Authenticate: Bearer realm="",client_id="",trusted_issuers="",authorization_uri="https://login.windows.net/common/oauth2/authorize"} 401 Exception in thread "main" java.lang.RuntimeException: Failed : HTTP error code : 401 at com.sharepointOnline.SharepointOnlineAuthenticator.getFolderByServerRelativeUrl(SharepointOnlineAuthenticator.java:99) at com.sharepointOnline.SharepointOnlineAuthenticator.main(SharepointOnlineAuthenticator.java:73)

Can someone please help with this error?

  • Did you try to use Office Graph instead of SharePoint API? – jaloplo Jul 31 at 14:37
  • can anybody send me the source code – Kiran Oct 14 at 4:28
3

Here is a demo for your reference, We access SharePoint online and use REST API to upload a file in JAVA.

1.Get the security token from Microsoft authentication portal:

public String receiveSecurityToken() throws TransformerException, URISyntaxException {

RequestEntity<String> requestEntity = 
    new RequestEntity<>(buildSecurityTokenRequestEnvelope(), 
    HttpMethod.POST, 
    new URI("https://login.microsoftonline.com/extSTS.srf"));

ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
DOMResult result = new DOMResult();

Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new StringSource(responseEntity.getBody()), result);

Document definitionDocument = (Document) result.getNode();
String securityToken = xPathExpression.evaluateAsString(definitionDocument);

if (StringUtils.isBlank(securityToken)) { 
    throw new SharePointAuthenticationException("Unable to authenticate: empty token");
}

    return securityToken;
}

The envelope that is sent to the portal has the following format:

<s:Envelope 
xmlns:s="http://www.w3.org/2003/05/soap-envelope" 
xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
    <a:ReplyTo>
        <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand="1">https://login.microsoftonline.com/extSTS.srf</a:To>
    <o:Security s:mustUnderstand="1" 
        xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <o:UsernameToken>
            <o:Username>[username]</o:Username>
            <o:Password>[password]</o:Password>
        </o:UsernameToken>
    </o:Security>
</s:Header>
<s:Body>
    <t:RequestSecurityToken 
        xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
        <wsp:AppliesTo 
            xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
            <a:EndpointReference>
                <a:Address>[SharePoint domain address]</a:Address>
            </a:EndpointReference>
        </wsp:AppliesTo>
        <t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
        <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
        <t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
    </t:RequestSecurityToken>
</s:Body>
</s:Envelope>

2.Get the cookies from the SharePoint Online server:

public List<String> getSignInCookies(String securityToken) throws TransformerException, URISyntaxException {

RequestEntity<String> requestEntity = 
    new RequestEntity<>(securityToken, 
        HttpMethod.POST, 
        new URI("[SharePoint domain address]/_forms/default.aspx?wa=wsignin1.0"));

ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
HttpHeaders headers = responseEntity.getHeaders();
List<String> cookies = headers.get("Set-Cookie");

if (CollectionUtils.isEmpty(cookies)) {
    throw new SharePointSignInException("Unable to sign in: no cookies returned in response");
} 

  return cookies;
}

3.Get the signature(FormDigestValue) for requests to the SharePoint Online server:

public String getFormDigestValue(List<String> cookies) throws IOException, URISyntaxException, 
TransformerException, JSONException {

MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("Cookie", Joiner.on(';').join(cookies));
headers.add("Accept", "application/json;odata=verbose");
headers.add("X-ClientService-ClientTag", "SDK-JAVA");

RequestEntity<String> requestEntity = new RequestEntity<>(headers, 
    HttpMethod.POST, new URI("[SharePoint domain address]/_api/contextinfo"));

ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
JSONObject json = new JSONObject(responseEntity.getBody());

return json.getJSONObject("d")
    .getJSONObject("GetContextWebInformation").getString("FormDigestValue"); 

}

Finally, we can call REST API to upload the document as below.

url: http://site url/_api/web/GetFolderByServerRelativeUrl('/Folder Name')/Files/add(url='a.txt',overwrite=true)

method: POST body: "Contents of file" Headers: Authorization: "Bearer " + accessToken X-RequestDigest: form digest value content-length:length of post body

public String performHttpRequest(String path, String json, boolean isUpdate) throws Exception {

String securityToken = receiveSecurityToken();
List<String> cookies = getSignInCookies(securityToken);
String formDigestValue = getFormDigestValue(cookies);

MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("Cookie", Joiner.on(';').join(cookies));
headers.add("Content-type", "application/json;odata=verbose");
headers.add("X-RequestDigest", formDigestValue);                     

RequestEntity<String> requestEntity = new RequestEntity<>(json, 
    headers, HttpMethod.POST, new URI(path));

ResponseEntity<String> responseEntity = 
    restTemplate.exchange(requestEntity, String.class);

return responseEntity.getBody();
}

More information for your reference: SharePoint Online remote authentication (and Doc upload)

You can refer to my answer: How to upload files to sharepoint site's document library using Graph API on android

  • where we have to pass this xml envelope ? – Anurag_BEHS Oct 14 '18 at 13:17
  • @Anurag_BEHS request to login.microsoftonline.com/extSTS.srf with post method – Lee Liu Oct 17 '18 at 2:16
  • do u mean we have to pass this xml envelope as post body of step 1 ? in step 1 method what is- buildSecurityTokenRequestEnvelope() method what we have to do here ? – Anurag_BEHS Oct 19 '18 at 17:55
  • @Anurag_BEHS Yes, we have to pass the xml envelope as post body of step 1, the code is not very detailed, it only porvide the idea. I recommend you to refer to: paulryan.com.au/2014/spo-remote-authentication-rest – Lee Liu Oct 22 '18 at 2:02
  • @LeeLiu In your answer you have used <o:Username>[username]</o:Username>, here username mainly is email address. So can we use anything else other then email address. – Pankaj Goyal Feb 11 at 12:00
0

Maybe my answer is a bit late, but, can't you use the Microsoft Graph ?

this is a quickstart from Microsoft for java development : https://github.com/OfficeDev/Office-365-SDK-for-Java

And the docs to connect to SPO : https://docs.microsoft.com/en-us/graph/api/resources/sharepoint?view=graph-rest-1.0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.