Authenticate (Node.js: Single-User App)#

Inrupt provides the solid-client-authn-node library to authenticate in Node.js.

npm install @inrupt/solid-client-authn-node

Node.js: Single-User Application#

Your application can use the solid-client-authn-node library to handle the user authentication flow.

Although your application can start the authentication flow that involves browser-based user interactions with a Solid Identity Provider, as an alternative, you can separately obtain refresh tokens and client credentials for use in your application.

That is, if your Solid Identity Provider supports refresh tokens and/or client credentials as grant types, then:

  1. As a prereq, you can first obtain:

    • refresh token and client credentials (from dynamic or static registration of the application), or

    • client credentials from static registration of the application.

    This is done separately from the application.

  2. Then, in your application, you can use either:

    • refresh tokens and client credentials, or

    • client credentials only if the application is statically registered.

Authenticate with Statically Registered Client Credentials#

Prerequisite#

If supported by your Solid Identity Provider, statically register your application. The registration results in a Client ID and Client Secret pair.

For example, if using the Solid Identity Provider for Inrupt’s Pod Spaces, you can statically register your application via its Inrupt Application Registration page.

Update Application Code#

For a statically registered application, you can use the solid-client-authn-node library with the client credentials for the the user authentication flow:

  1. Create a new Session for the user.

  2. Call the Session.login() function, passing in the ILoginInputOptions.

    Although you can pass in the options (oidcIssuer, redirectUrl, handleRedirect) to start the authentication flow, you can instead pass in the following options with the values obtained from the prerequisite section to login without the manual, browser-based user interactions:

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

Warning

Safeguard your clientId and clientSecret values. Do not share these with any third parties as anyone with your clientId and clientSecret values can impersonate you and act fully on your behalf.

Example#

The following single-user application calls Session.login() with:

  • clientId, clientSecret, and

  • oidcIssuer.

Warning

Safeguard your clientId and clientSecret values. Do not share these with any third parties as anyone with your clientId and clientSecret values can impersonate you and act fully on your behalf.

const { Session } = require("@inrupt/solid-client-authn-node");

// 1. Get the authenticated credentials: myClientId, myClientSecret
// and myIdentityProvider, the Solid Identity Provider associated with the credentials.
// ...
// ...
// Important: Safeguard these credentials.

const session = new Session();
session.login({
  // 2. Use the authenticated credentials to log in the session.
  clientId: myClientId,
  clientSecret: myClientSecret,
  oidcIssuer: myIdentityProvider
}).then(() => {
  if (session.info.isLoggedIn) {
    // 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);
  }
});

Static Registration of a Client Application#

If your Solid Identity Provider provides a mechanism to statically register applications, your applications can use the associated client credentials to login.

Availability#

Inrupt’s PodSpaces provides an Application Registration page where you can statically register your applications to generate credentials for them. It is available for users with accounts on https://login.inrupt.com; i.e., users who have registered a Pod with PodSpaces. To use, visit the Application Registration to register your client.

For availability of static client registration for your Solid Identity Provider, see your Solid Identity Provider’s documentation.

Authenticate with a Refresh Token#

Your application can use Refresh Token to get an Access Token. Access Tokens allows you to access Resources for which you have been authorized.

Prerequisite#

Obtain a Refresh Token and client credentials for your application.

Update Application Code#

To handle the authentication flow with the solid-client-authn-node library and a Refresh Token (and the client credentials):

  1. Create a new Session for the user.

  2. Call the Session.login() function, passing in the ILoginInputOptions.

    Although you can pass in the options (oidcIssuer, redirectUrl, handleRedirect) to start the authentication flow, you can instead pass in the following options with the values obtained from the prerequisite section to login without the manual, browser-based user interactions:

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

Warning

Safeguard your clientId, clientSecret, and refreshToken values. Do not share these with any third parties as anyone with your clientId, clientSecret, and refreshToken values can impersonate you and act fully on your behalf.

Example#

The following single-user application calls Session.login() with:

  • clientId, clientSecret, refreshToken, and

  • oidcIssuer.

Warning

Safeguard your clientId, clientSecret, and refreshToken values. Do not share these with any third parties as anyone with your clientId, clientSecret, and refreshToken values can impersonate you and act fully on your behalf.

const { Session } = require("@inrupt/solid-client-authn-node");

// 1. Get the authenticated credentials: 
//     myClientId, myClientSecret, myRefreshToken, myIdentityProvider
// ...
// ...
// Important: Safeguard these credentials.

const session = new Session();

// For the Session, specify the callback to invoke when the refresh token is updated by the Identity Provider.
session.onNewRefreshToken((newToken) => {
  console.log('New refresh token: ', newToken);
});

session.login({
  // 2. Use the authenticated credentials to log in the session.
  clientId: myClientId,
  clientSecret: myClientSecret,
  refreshToken: myRefreshToken,
  oidcIssuer: myIdentityProvider
}).then(() => {
  if (session.info.isLoggedIn) {
    // 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);
  }
});

Handling Refresh Token Rotation#

Refresh Tokens allow you to get a new Access Token when the previous Access Token expires. Refresh Tokens should be treated as sensitive data since the new Access Tokens allow authenticated access to resources. As such, it is considered good practice for Solid Identity Provider to implement a “Refresh Token rotation” process. That is, 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 Node.js applications 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.