Solid Interface development

To be even clearer - if you us solid-node-client to ogin with a token, you are using Inrupt’s client library. Inrupt’s library does not support username/password login from the command line so if that’s the way you login, the answer is no you can’t use Inrupt’s library for that.

Thanks Jeff. In waiting for your answer I went to inform me again and confirm when you say.

I still remain tied to the tool knot for the token. Unfortunately I understand what I receive and how to use what was said (the various clients, refreshtoken etc), but I didn’t understand how to use that tool for my context

The short answer is, if you need to use username/password login outside a GUI, your only choice is solid-node-client and using it you can ignore the token, there is nothing about the token you need to manage.

My desire is to use the tool to obtain a token to authenticate all the app/user(s) in my context.

As you said previously, the token generated by that tool will be expired after 3 days, and can be used to login without pass each time to the GUI interaction.
(however the repository tell 3 weeks with NSS - so, using inrupt)

As Admin of the Pod that i need to interact with, how i should use that tool? the questions it (the tool) poses me doesn’t help me to understand how to move.

This is the sequence of question:

  • What Solid Identity Provider do you want to log in to?
    Anser was broker.inrupt.com

  • Has Your App Been Pre-Registered by The Administrator Of The Pod Server You Are Signing In To?
    Answer could be Yes or No

  • What Is the Name of the Application You Are Registering?
    Answer will be a name like “Something”

  • Then i obtain the login link to use to login on inrupt.

I want to repeat: I need to understand how to perform these steps as a pod administrator with which I want to interact, to allow me to get all the tokens for my app / user I want to log in to my pod without using GUI login

The questions about the App being preregistered and the name of the application CAN BE IGNORED because, as far as I know, they are not used at the moment. There are plans for registering apps but those are not implemented yet. @zwifi - will you please confirm if I am correct that these questions can be ignored? I find their inclusion in the token tool quite confusing, as apparently do others.

okok, so there is an evident confusion on that. ok.

“There are plans for registering apps but those are not implemented yet”.
with this above what do you mean exactly?
i need to login in a Pod with 2 external users that will be implemented by two local site/server (for instance a web restaurant, and a store).

I almost forgot !! I would like to login as a pod administrator using the token obtained from that tool
how can i do using that tool at the moment? Considered what are the questions that it poses

“There are plans for registering apps but those are not implemented yet”.
with this above what do you mean exactly?

I gave you as much information as I have.

I would like to login as a pod administrator using the token obtained from that tool how can i do using that tool at the moment?

There is extensive documentation at Inrupt JavaScript Client Libraries — Inrupt JavaScript Client Libraries. I suggest you read that and try some of the tutorials that help you build apps with login ability.

ok.

i have read those documentations, also about the session.login() function. It needs the params that the https://www.npmjs.com/package/@inrupt/generate-oidc-token tool return with the token.

the section with the explanation to login without GUI tells to use this tool as in https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/authenticate-nodejs/ in the section " Node.js Script: Single-User Script ".
Here:

you can instead pass in the following options (whose already-registered values you obtain from completing the authentication flow separately from the script) to have an authenticated session without the manual, in-browser redirect interactions:

  • An already-registered clientId, which identifies your application to the Solid Identity Provider.
  • An already-registered clientSecret, associated to the Client ID.
  • An already-registered refreshToken, which your application can use to get an Access Token. Access Tokens allows you to access Resources for which you have been authorized.
  • oidcIssuer, the Solid Identity Provider where your Client ID , Client Secret , and Refresh Token have been registered.

When login() returns, your session should be logged in and able to make authenticated requests.

and still…

In a terminal, run generate-oidc-token utility to log in to a

npx @inrupt/generate-oidc-token

The utility prompts the user for some information.

Enter the appropriate values to the prompts.

When finished, the utility asks the user to visit a site in a browser.

Open the browser and visit the site. Log in to the Solid Identity Provider.

Upon login, return to the terminal and you should see the following information:

Client ID

Client Secret

Refresh Token

considering those informations, even if i m either the admin or an external user, I should still use that tool to log in without GUI. Correct?

i hope someone could help me to understand how to interact with the tool both as admin or external user

  1. Run generate-oidc-token to get a token from your Identity provider for a user, lets say user_A
  2. In your app, use the token you get from step1 to login to your Identity Provider
  3. In your app visit any pod where user_A has privileges (could be admin privileges or just read for others). Your app can now do whatever user_A is authorized to do.

And to stress again … generate-oidc-token and the steps I showed above are only for out-of-browser apps. For browser apps, just do as the Inrupt tutorials show you.

what do you mean with “out-of-browser app”? could you make an example?

The link inserted in the prev response talk about a nodejs script (out of browser) login, as in my case.
At the moment i m trying to login with a nodejs initialization script, and still isLoggedIn = false .
So i think the problem is with the tool and how to use it. Still on that link you can find also a code snippet that show the usage of the code part, where i started, but it tells less on usage of that tool.

Trying to answer to your steps:

  1. Run generate-oidc-token to get a token from your Identity provider for a user, lets say user_A

i need to understand this, mainly with how to fill its fields. I m trying during this time with each combination on the tool, but still isLoggedIn=false

what do you mean with “out-of-browser app”?

I mean a nodejs script.

I m trying during this time with each combination on the tool, but still isLoggedIn=false

Please show your code (but first replace the token and other login information with XXX so you don’t share your login info)

Ok jeff, look here.

function logging(sessionID, provider, myClientId, myClientSecret, myRefreshToken){

    sessionID += createSessionID();

    const session = new Session(

      {

        //clientAuthentication: getClientAuthenticationWithDependencies({})

        //public readonly info: ISessionInfo,

        //storage: IStorage;  //set-delete-get

        //tokenRequestInProgress = false,

        //onNewRefreshToken?: (newToken: string) => unknown

        //defaultMaxListeners: number,

        //errorMonitor: typeof errorMonitor,

      },

      sessionID

    );

    try {

      session.login({

        // Set oidcIssuer to the Solid Identity Provider associated with the credentials.

        oidcIssuer: provider,

 

        //An already-registered clientId, which identifies your application to the Solid Identity Provider.

        clientId: myClientId,

 

        //An already-registered clientSecret, associated to the Client ID. Like a password

        clientSecret: myClientSecret,

 

        //An already-registered refreshToken, which your application can use to get an Access Token.

        //Access Tokens allows you to access Resources for which you have been authorized.

        refreshToken: myRefreshToken,

 

        /**

         * each time the client application uses a Refresh Token to get a new Access Token,

         *  a new Refresh Token is also returned. The previous Refresh Token is invalidated,

         *  and can no longer be used to get Access Tokens

         */

        // If the refresh token is updated by the Identity Provider, this callback gets invoked.

        onNewRefreshToken: (newToken) => {

          console.log("New refresh token: ", newToken);   //to be stored in some way

          //myRefreshToken = newToken;

        }

      }).then(() => {

        if (session.info.isLoggedIn) {

          /**

          * The WebID of the app, or a "Public app" WebID if the app does not provide its own.

          * undefined until the session is logged in and the app WebID has been verified.

          */

          console.log(session.info.clientAppId);

          //The WebID if the user is logged into the session, and undefined if not

          console.log(session.info.webId);

          /**

            * UNIX timestamp (number of milliseconds since Jan 1st 1970) representing the

            * time until which this session is valid.

            */

          console.log(session.info.expirationDate);          

          // 3. Your session should now be logged in, and able to make authenticated requests.

          session

            // You can change the fetched URL to a private resource, such as your Pod root.

            .fetch(session.info.webId)

            .then((response) => {

              return response.text();

            })

            .then(console.log);

        }

      });

 

      //print(session.info.isLoggedIn);

      console.log(session.info.sessionId);

     

      return session;      

    } catch (error) {

      console.log(error);

    }  

}

this is the function i use to login. i have already check all the variables values, and are passed ok.
As we can see, i pass

provider, myClientId, myClientSecret, myRefreshToken

potentially obtained from the tool generate-oidc-token, so to be passed to session.login().

What is the value of provider? (who is your Identity Provider).

At first glance, your code looks okay to me. I suggest you contact Inrupt support at Issues & Help — Inrupt JavaScript Client Libraries. Sorry, I’ve done all I could. Good luck!

the provider is always broker.inrupt.com in my context.

thanks jeff, i hope someone could help me to complete the login

Hi everyone. Finally i logged in my Pod using the tool generate-oidc-token.
simply when it starts i press always ok (so no filling any field, only the provider choice), and then login to the provider with the user that i want to obtain the token to use within nodejs code.
Now this work, and return me a logged session. Fine. I ve worked a lot on my code to see some details explained.

However, i have still a consideration to make, but this is personal to my code, not solid-related.

async function logging(sessionID, token){

    sessionID += createSessionID();

    const session = new Session(

      {

        //clientAuthentication: getClientAuthenticationWithDependencies({})

        //public readonly info: ISessionInfo,

        //storage: IStorage;  //set-delete-get

        //tokenRequestInProgress = false,

        //onNewRefreshToken?: (newToken: string) => unknown

        onNewRefreshToken: (newToken) => {

          console.log("New refresh token: ", newToken);   //to be stored in some way

          myRefreshToken = newToken;

        }

        //defaultMaxListeners: number,

        //errorMonitor: typeof errorMonitor,

      },

      sessionID

    );

    return await session.login({

      // Set oidcIssuer to the Solid Identity Provider associated with the credentials.

      oidcIssuer: token.provider,

      //An already-registered clientId, which identifies your application to the Solid Identity Provider.

      clientId: token.clientId,

      //An already-registered clientSecret, associated to the Client ID. Like a password

      clientSecret: token.clientSecret,

      //An already-registered refreshToken, which your application can use to get an Access Token.

      //Access Tokens allows you to access Resources for which you have been authorized.

      refreshToken: token.refreshToken      

    })

    .then(() => {

      if (session.info.isLoggedIn) {

        console.log("I m logged in :", session.info.isLoggedIn);

        /**

        * The WebID of the app, or a "Public app" WebID if the app does not provide its own.

        * undefined until the session is logged in and the app WebID has been verified.

        */

        console.log("clientAppId: ",session.info.clientAppId);

        //The WebID if the user is logged into the session, and undefined if not

        console.log("WebID: ",session.info.webId);

        /**

          * UNIX timestamp (number of milliseconds since Jan 1st 1970) representing the

          * time until which this session is valid.

          */

        console.log("Expiration Date: ",session.info.expirationDate);                

      }

      else

        console.log("You are not logged");  

    });  

}

this is the function where i create the Session and call the login function. It works finally, but return nothing. I cannot return the session (logged). Why? what is wrong in the code?

No need to apologise for trying to learn, although please also recognise that I’m not trying to mislead. However, I’m trying to address fundamental misconceptions that lead to what I think is asking the wrong questions. I think that because answering your questions directly looks as follows:

how can I activate what was written above?

You can’t; you can’t set access for app1 and app2, and you can’t create accounts for apps on Inrupt.

I tried to explain the reason for that above.

Note, in case it’s a typo here on the forum: the correct (and non-obvious) URL is broker.pod.inrupt.com - you missed the .pod.

Goodevening everyone.
I managed to solve the problem of the login and to log in. Well Done.

Continuous with another series of applications related to Solid development:

  • I now find myself having to manage requests with necessary authorization, or the fetch. I found the Fetch () function in @inrupt/solid-client-authn-node. In the official documentation, the examples that show me as the word “fetch” is used “as an authorization parameter”. We can import fetch (but this seems to be the case of browser context).
    import { login, fetch } from "@inrupt/solid-client-authn-browser";
    While with Node library this seems to not be “importable”, in the sense that “importing” or “requiring” this function within node script, this is not available (same for other function e.g. setAccessFor).
    When i use {fetch : fetch} i obtain this error config.json is not a function related to the index.js in solid at this code:
async function getResourceInfo(url, options = Object.assign(Object.assign({}, internal_defaultFetchOptions), { ignoreAuthenticationErrors: false })) {
    var _a;
    const config = Object.assign(Object.assign({}, internal_defaultFetchOptions), options);
    const response = await config.fetch(url, { method: "HEAD" });
    return responseToResourceInfo(response, {
        ignoreAuthenticationErrors: (_a = options.ignoreAuthenticationErrors) !== null && _a !== void 0 ? _a : false,
    });
}

and going deeper i found this (always in index.js within @inrupt/solid-client-authn-node)

const fetch = async (resource, init) => {
    /* istanbul ignore if: `require` is always defined in the unit test environment */
    if (typeof window === "object" && typeof require !== "function") {
        return await window.fetch(resource, init);
    }
    /* istanbul ignore if: `require` is always defined in the unit test environment */
    if (typeof require !== "function") {
        // When using Node.js with ES Modules, require is not defined:
        const crossFetchModule = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('cross-fetch')); });
        const fetch = crossFetchModule.default;
        return fetch(resource, init);
    }
    // Implementation note: it's up to the client application to resolve these module names to the
    // respective npm packages. At least one commonly used tool (Webpack) is only able to do that if
    // the module names are literal strings.
    // Additionally, Webpack throws a warning in a way that halts compilation for at least Next.js
    // when using native Javascript dynamic imports (`import()`), whereas `require()` just logs a
    // warning. Since the use of package names instead of file names requires a bundles anyway, this
    // should not have any practical consequences. For more background, see:
    // https://github.com/webpack/webpack/issues/7713
    let fetch;
    // Unfortunately solid-client-authn-browser does not support a default session yet.
    // Once it does, we can auto-detect if it is available and use it as follows:
    // try {
    //   fetch = require("solid-client-authn-browser").fetch;
    // } catch (e) {
    // When enabling the above, make sure to add a similar try {...} catch block using `import`
    // statements in the elseif above.
    // eslint-disable-next-line prefer-const
    fetch = require("cross-fetch");
    // }
    return await fetch(resource, init);
};

This is what i saw as error output

  • I can’t understand the mechanism of generating a new token after logging. What is specified as “Handling refresh token rotation”. In particular, known that, once you have obtained the token through the tool, this “expires” immediately after its (first and only) use. I believed that “Expiration Date” refer to the general duration of the token, and not at the expiry of the same. Where am I wrong to reason?
    In any case, the explanation of the mechanism cites:

"…each time the client application uses a Refresh Token to get a new Access Token, a new Refresh Token is also returned. The previous Refresh Token is invalidated, and can no longer be used to get Access Tokens.

@inrupt/solid-client-authn-node has an internal mechanism to manage refresh tokens in the Session’s storage. For the Session’s storage, you can pass in a storage as an option to the Session constructor or use the default storage, which is an in-memory storage. If you pass in a persistent storage, the refresh token management is transparent. However, for NodeJS scripts that use the Session’s default in-memory storage, the storage (and hence the refresh token) is lost when the program stops.

As an alternative to providing a persistent storage to the Session constructor, you can pass in the onNewRefreshToken callback to the constructor instead. Then, each time a new refresh token is issued, the onNewRefreshToken callback is invoked with the new refresh token as a parameter. The onNewRefreshToken option allows you to run custom code to handle the refresh token as appropriate.

I tried the use of onNewRefreshToken, but I couldn’t get anything and I’m still forced to use the tool for every time I have to test my code to log in.
Do you have usage suggestions ??

  • I’d better understand how the storage mechanism works. I saw from the Default documentation it is InMemory (which then loses everything after closing), while I saw setting examples on .json

  • When I receive an unauthorized error 401 while using functions to upload files what is telling me? What the authentication parameters didn’t work? I am referring to passing “fetch”