How to transmit data by api after logined successfully from the browser

I want open browser to login solid pod in my app,then get the solid data by api. But It’s not going well, i have no idea how to achieve my idea.
testapi.js

var express = require('express');
var router = express.Router();
//var test111 = require('../public/javascripts/test');
var test111 = require('../public/javascripts/test');
//var myDataset = require('../src/index');

/* GET users listing. */
router.get('/', async (req, res) => {
  //test111.aaa();
  var status = await test111.myDa
    console.log('database:',myDataset);
  res.send('status');
});

module.exports = router;

test.js

//const{handleIncomingRedirect} = require('@inrupt/solid-client-authn-browser')
const { 
    getSolidDataset,
    createSolidDataset,
    saveSolidDatasetInContainer,
  getThing,
  getDatetime,
  getStringNoLocale,
  getUrlAll,
  getUrl,
  getThingAll,
  addDatetime,
  createThing,
  setThing,
  addUrl,addStringNoLocale,
  saveSolidDatasetAt,addTerm,removeThing
  
  } = require("@inrupt/solid-client");
  const {fetch} = require('@inrupt/solid-client-authn-browser');

var test111={
    // 选择nss认证方式的登录
    aaa:function(){
      console.log('zheshige ceshi!!');
    },
    // handleRedirectAfterLogin:async function(){
    //     var status = false;
    //     await handleIncomingRedirect();
      
    //     const session = getDefaultSession();
    //     if (session.info.isLoggedIn) {
    //       // Update the page with the status.
    //       status = true;
    //       return status;
    //     }
    // }
    test: async function(){
        const myDataset = await getSolidDataset('https://pod.inrupt.com/liwenjing/profile/card', { fetch: fetch });
        console.log(myDataset);
    }


}
module.exports= test111;

After i logined solid pod,i access http://localhost:3000/testapi, get the error as follow:

Hi @wenjingli-qa, it looks like you’re creating a Node server and are trying to use solid-client-authn-browser. However, as its name implies, that library is intended for use in the browser. If you want to make authenticated requests on the server, you’ll want to use solid-client-authn-node, whose documentation you can find here.

1 Like

@Vincent Thank you so much for your help! But there is an error when i run the example following the tutorial of solid-client-authn-node.Authenticate (Node.js) — Inrupt JavaScript Client Libraries

app.get("/fetch", async (req, res, next) => {
  const session = await getSessionFromStorage(req.session.sessionId);
  console.log("resource",req.query["resource"]);
  console.log(await (await session.fetch(req.query["resource"])).text());
  res.send("<p>Performed authenticated fetch.</p>");
});

There is an error when i access http://localhost:3000/fetch,req.query[“resource”] is undefined.Is there something wrong with my operation? May I ask how to solve this problem?

resource undefined
(node:3428) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'toString' of undefined
    at ClientAuthentication.fetch (D:\solid-node\node_modules\@inrupt\solid-client-authn-node\dist\authenticatedFetch\fetchFactory.js:91:87)
    at Session.fetch (D:\solid-node\node_modules\@inrupt\solid-client-authn-node\dist\Session.js:28:46)
    at D:\solid-node\app.js:78:36
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:3428) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or
by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)

Hi @wenjingli-qa, the docs are a bit unclear about that, but if you’re familiar with Express, you’ll see that req.query refers to the URL’s query parameters.

In other words, you’ll have to pass the URL of the resource you want to fetch via ?resource=<resource URL> - and don’t forget to encode that URL.

So for example: http://localhost:300/fetch?resource=https%3A%2F%2Fpod.inrupt.com%2Fvincent%2Fprofile%2Fcard

@Vincent You’re right,the problem has been solved,thank you very much :smiley:!

@Vincent I have a new problem :cry:,could you help me?
i try to use postman send request to /fetch to get infomation,but it not usefull.
I have logined pod in browser by access http://localhost:3001/login,but when i send request to /fetch by postman,can’t get session info

app.get("/login", async (req, res, next) => {
    // 1. Create a new Session
    
    const session = new Session();
    req.session.sessionId = session.info.sessionId;
    const redirectToSolidIdentityProvider = (url) => {
      // Since we use Express in this example, we can call `res.redirect` to send the user to the
      // given URL, but the specific method of redirection depend on your app's particular setup.
      // For example, if you are writing a command line app, this might simply display a prompt for
      // the user to visit the given URL in their browser.
      res.redirect(url);
    };
    // 2. Start the login process; redirect handler will handle sending the user to their
    //    Solid Identity Provider.
    await session.login({
      // After login, the Solid Identity Provider will send the user back to the following
      // URL, with the data necessary to complete the authentication process
      // appended as query parameters:
      redirectUrl: `http://localhost:${port}/redirect-from-solid-idp`,
      // Set to the user's Solid Identity Provider; e.g., "https://broker.pod.inrupt.com" 
      oidcIssuer: "https://solidcommunity.net",
      // Pick an application name that will be shown when asked 
      // to approve the application's access to the requested data.
      clientName: "Demo app",
      handleRedirect: redirectToSolidIdentityProvider,
    });
  });
  
  app.get("/redirect-from-solid-idp", async (req, res) => {
    // 3. If the user is sent back to the `redirectUrl` provided in step 2,
    //    it means that the login has been initiated and can be completed. In
    //    particular, initiating the login stores the session in storage, 
    //    which means it can be retrieved as follows.
    console.log(app.locals.sessionId);
    app.locals.sessionId=req.session.sessionId;
    const session = await getSessionFromStorage(req.session.sessionId);
  
    // 4. With your session back from storage, you are now able to 
    //    complete the login process using the data appended to it as query
    //    parameters in req.url by the Solid Identity Provider:
    await session.handleIncomingRedirect(`http://localhost:${port}${req.url}`);
  
    // 5. `session` now contains an authenticated Session instance.
    if (session.info.isLoggedIn) {
      return res.send(`<p>登录成功,请返回上一页</p>`)
    }
  });
  
  // 6. Once you are logged in, you can retrieve the session from storage, 
  //    and perform authenticated fetches.
  app.get("/fetch", async (req, res, next) => {
    // if(typeof req.query["resource"] === "undefined") {
    //   res.send(
    //     "<p>Please pass the (encoded) URL of the Resource you want to fetch using `?resource=&lt;resource URL&gt;`.</p>"
    //   );
    // }
    console.log(app.locals.sessionId);
    console.log(req.session.sessionId);
    const session = await getSessionFromStorage(app.locals.sessionId);
    console.log('session',session);
    var podURL = 'https://liwenjing.solidcommunity.net/getting-started/readingList/myList';

    //const mylinktree = podURLG;
    let myPodFolder = await getSolidDataset(podURL,{fetch:session.fetch});
    console.log('llllllfolder',myPodFolder);
    var thingName = [];
    //var linkimage = [];
    let urlarray = getThingAll(myPodFolder);
    var linklink = [];
    var linkinfo = [];
    //
    for(i=0;i<urlarray.length;i++){
      thingName[i] = urlarray[i].internal_url.split('#')[1]
      linklink = thingName[i].split('-');
      //console.log(linklink);
      if(linklink[linklink.length-1]!='url'){
      //console.log(linklink[linklink.length-1]);
        var thingurl = podURL+'#'+thingName[i];
      //console.log(thingurl);
        let things = getThing(myPodFolder,thingurl);
      //console.log('things.................',things);
        var imageuuu = getUrl(things,schema.url);
        var hhh = getStringNoLocale(things,schema.name);
        var modifiedDateTime = getDatetime(things,schema.dateModified)
        linkinfo.push({id:thingName[i],imageurl:imageuuu,name:hhh,modifieddate:modifiedDateTime});
        
    }
  };
  console.log('linkinfo111111111111111111111',linkinfo);
  //return linkinfo;
  res.status(201).send({linkinfo});
 


    // console.log(await (await session.fetch(req.query["resource"])).text());
    // res.send("<p>Performed authenticated fetch.</p>");
  });

after send request use postman, the error as follow

session undefined
(node:19164) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'fetch' of undefined
    at D:\FUXI-Link微信小程序\FUXI-Link\express-hello-world\app.js:146:67
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:19164) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:19164) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

It’s probably best to post that in a separate topic so others can read along and possibly help you too, since I don’t know everything :slight_smile:

So it looks like getSessionFromStorage returns undefined. I’m not too familiar with that, but could you check whether app.locals.sessionId has a value, and whether that value matches the session ID you see elsewhere (e.g. in the /login callback)?