4

In my node.js app, I want to make a rest call to sharepoint 2013. This is the node.js code

function downloadData(res, key, success, fail) {    
    var opts = url.parse(key);


    opts.method = 'GET';
    opts.headers = {"Accept":"application/json;odata=verbose","X-RequestDigest":"0x146E2BDC9A21FDA62E793A0FC9793A530A5C6688BE194FB051703C8529B01A16607931C77D26EE61FA360AD04526F476A052FAC9B3C9277A5463AC20A27C3543,07 Mar 2016 15:37:18 -0000"};
    opts.headers['Content-Type'] = 'application/json;odata=nometadata';

    var req = http.request(opts, function(response) {
        var str = '';

        //another chunk of data has been recieved, so append it to `str`
        response.on('data', function (chunk) {
            str += chunk;
        });

        //the whole response has been recieved, so we just print it out here
        response.on('end', function () {
            success(res, str, key);
        });
    })

    //req.write(data);
    req.end();
}

I got the digest value from the client side, I did an alert statement, and copied it. I tried it on a sample url, which does work if I paste on the browser. When I run this, I get 401 unauthorized.

Does anyone know what's wrong?

Thanks


Here is what I have so far:

js

            $.ajax({
                url: "http://myserver:3000/_api/web/lists/GetByTitle('NewsNews')/items",
                type: "GET", 
                headers: {
                            "Accept": "application/json;odata=verbose",
                            "X-RequestDigest": $("#__REQUESTDIGEST").val()
                        },
                success: function (data) {
                    alert(JSON.stringify(data));
                },
                error: function (jqxr, errorCode, errorThrown) {
                    alert("failed");
                }
            });

node.js

var express = require('express');
var app = express();
var http = require('http');
var url = require('url');

var cacheObj = {};

app.get('/_api/web*', function (req, res) {
    var key = req.originalUrl;
    req.headers["Content-Type"] = "application/json;odata=nometadata";
    res.setHeader('Content-Type', 'application/json');
    processIncomingCall(key, res, req.headers);
});

function processIncomingCall(key, res, headers) {
    var val = cacheObj[key];

    if (val) {
        console.log(val);
        res.send(JSON.stringify(val));
    } else {
        downloadData(res, key, headers, function(res, data, key) {
            cacheObj[key] = data;
            setTimeout(function(key) {
                delete cacheObj[key];
            }, 1000 * 5, key);
            res.send(JSON.stringify(data));
        }, function() {

        });
    }
}

function downloadData(res, key, headers, success, fail) {
    var opts = url.parse(key);
    opts.method = 'GET';
    opts.headers = headers;

    var req = http.request(opts, function(response) {
        var str = '';

        //another chunk of data has been recieved, so append it to `str`
        response.on('data', function (chunk) {
            str += chunk;
        });

        //the whole response has been recieved, so we just print it out here
        response.on('end', function () {
            success(res, str, key);
        });
    })

    //req.write(data);
    req.end();
}

var server = app.listen(3000, function () {
    var host = server.address().address;
    var port = server.address().port;

    console.log('Started at http://%s:%s', host, port);
});
3

You can also try sp-request
With sp-request you can easily send REST queires:

var spr = require('sp-request').create(credentialOptions);
spr.get('http://sp2013dev/sites/dev/_api/web/lists/GetByTitle(\'TestList\')')
  .then(function (response) {
    console.log('List Id: ' + response.body.d.Id);
  })
  .catch(function(err){
    console.log('Ohhh, something went wrong...');
  });
0

There are two things which must be in place:

1. The Authorization Header: EndpointRequest.Headers.Add("Authorization", "Bearer " + accessToken);

2. Request Digest, (as you already know): It would be best if you get a new one every time. You do this by calling siteulrl/_api/contextinfo and parsing the token from the xml file.

As Andrey statet, look a the JSOM Package it uses the same authentication mechanisms as the REST interface. So the authentication code should be around there. Using Fiddler, you can also take a closer look at your http-Headers.

  • What I am doing is making a node.js middle man on my farm, so when a user makes a rest call from the client side, I change it to go to my node.js process, then make the actual rest call from there. So is it possible I can forward the authentication from the client to the node.js process when node.js makes the rest call? So the node.js rest calls runs as the user from the client side. – omega Mar 7 '16 at 17:13
  • Actually that is possible. It is called delegation. It is usually done with kerberos. But is quite a big topic and maybe it is okay for your purposes to work perform your requests with a system account. – Harry Berry Mar 7 '16 at 17:38
  • Actually I need it to use the current user rather than a system account, as REST calls gets security trimmed, so I need user accounts. – omega Mar 7 '16 at 17:39
  • I tried, taking the digest information that the client sends to the server, get that in node, then set that header in the http request in node, but I still get 401 unauthorized. – omega Mar 7 '16 at 17:43
  • Yes that is because you are still missing the authorization header, that is not the same as the request digest. You have basically 2 options: Configure kerberos if you are on premise or use oauth if you are using sharepoint online. The problem you are facing right now is called "double hop problem", you will find a lot of information on the web about that 😉 – Harry Berry Mar 7 '16 at 21:31

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.