From 22791662ad9142fb3bcf140288656a07301e123f Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sun, 15 Feb 2026 20:45:24 +0000 Subject: [PATCH 1/6] feat: add guide for authenticating with a script --- docs/guides/authenticating_with_a_script.md | 127 ++++++++++++++++++++ docs/index.md | 5 +- 2 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 docs/guides/authenticating_with_a_script.md diff --git a/docs/guides/authenticating_with_a_script.md b/docs/guides/authenticating_with_a_script.md new file mode 100644 index 0000000..f07e3da --- /dev/null +++ b/docs/guides/authenticating_with_a_script.md @@ -0,0 +1,127 @@ +# Authenticating with a Node.js Script + +Many Solid use cases — automated data pipelines, bots, CI/CD tasks, and server-to-server integrations — require authentication **without a browser**. This guide walks you through authenticating a Node.js script against a Solid server using **Client Credentials**. + +The approach works with any Solid server that supports the Client Credentials grant type, including the [Community Solid Server (CSS)](https://communitysolidserver.github.io/CommunitySolidServer/) and Inrupt's [Enterprise Solid Server (ESS)](https://docs.inrupt.com/). + +## Prerequisites + +- [Node.js](https://nodejs.org/) v18 or later (for built-in `fetch`) +- A Solid account with a Pod on a server that supports Client Credentials +- Basic familiarity with JavaScript + +## Overview + +The flow has three stages: + +1. **Generate a Client Credentials token** — obtain a `client_id` / `client_secret` pair linked to your WebID. This only needs to be done **once**. +2. **Log in with the credentials** — use the `client_id` and `client_secret` to start an authenticated session. +3. **Make authenticated requests** — use the session's `fetch` to read and write resources on your Pod. + +## 1. Set Up the Project + +Create a new directory and initialise it: + +```bash +mkdir solid-script && cd solid-script +npm init -y +``` + +Set the project to use ES modules and install the required library: + +```bash +npm pkg set type=module +npm install @inrupt/solid-client-authn-node +``` + +Create a file called `index.js` — all the code below goes into this file. + +## 2. Generate Client Credentials (One-Time Setup) + +Before your script can log in, you need a `client_id` / `client_secret` pair. There are two ways to get one: + +### Option A: Via the Account Page (easiest) + +If your Solid server has an account management UI, you can create a token there: + +1. Navigate to your account page: + - **Community Solid Server (local)**: [http://localhost:3000/.account/](http://localhost:3000/.account/) + - **solidcommunity.net**: [https://solidcommunity.net/.account/](https://solidcommunity.net/.account/) + - **Inrupt PodSpaces**: [https://login.inrupt.com/registration.html](https://login.inrupt.com/registration.html) +2. Create a new Client Credentials token, giving it a name and selecting your WebID. +3. Copy the `id` and `secret` values shown. **Store the secret safely** — it cannot be retrieved again. + +Skip ahead to [Step 3](#3-log-in-and-make-authenticated-requests) if you use this approach. + +### Option B: Via the API (programmatic) + +Some Solid servers also allow you to generate credentials programmatically. This is useful for automation or when you don't have browser access. The process is server-specific — for example, the Community Solid Server provides a dedicated API for this: + +- [CSS — Generating a token via the API](https://communitysolidserver.github.io/CommunitySolidServer/latest/usage/client-credentials/#via-the-api) + +## 3. Log In and Make Authenticated Requests + +Once you have a `client_id` and `client_secret`, you can authenticate using the [`Session`](https://inrupt.github.io/solid-client-authn-js/node/classes/Session.html) class from `@inrupt/solid-client-authn-node`. + +Replace the contents of `index.js` (or create a new file) with: + +```javascript +import { Session } from '@inrupt/solid-client-authn-node'; + +// These values come from Step 2 (or from your account page). +// In production, load these from environment variables. +const CLIENT_ID = process.env.SOLID_CLIENT_ID; +const CLIENT_SECRET = process.env.SOLID_CLIENT_SECRET; +const OIDC_ISSUER = 'http://localhost:3000'; // Your Solid server URL + +async function main() { + // Create a new session and log in + const session = new Session(); + await session.login({ + clientId: CLIENT_ID, + clientSecret: CLIENT_SECRET, + oidcIssuer: OIDC_ISSUER, + }); + + if (!session.info.isLoggedIn) { + throw new Error('Login failed'); + } + console.log(`Logged in as ${session.info.webId}`); + + // session.fetch works just like the standard fetch API, + // but automatically includes authentication headers. + const response = await session.fetch(session.info.webId); + console.log(`GET ${session.info.webId} — ${response.status}`); + console.log(await response.text()); + + // Always log out when done + await session.logout(); + console.log('Logged out.'); +} + +main().catch(console.error); +``` + +Run the script: + +```bash +SOLID_CLIENT_ID="your-client-id" \ +SOLID_CLIENT_SECRET="your-client-secret" \ +node index.js +``` + +You should see your profile document printed to the console. + +## Tips + +- **Token reuse**: The `client_id` / `client_secret` pair does not expire. Generate it once and reuse it across runs. Only the access tokens obtained during `session.login()` are short-lived — the library handles refreshing them automatically. +- **Session keep-alive**: By default, the `Session` refreshes its tokens in the background. Pass `{ keepAlive: false }` to the `Session` constructor if you want a one-shot script that exits cleanly. +- **Security**: Never hard-code secrets in source code. Use environment variables or a secrets manager. +- **Multiple WebIDs**: You can generate multiple client credentials tokens, each linked to a different WebID on your account. + +## Further Reading + +- [Community Solid Server — Client Credentials documentation](https://communitysolidserver.github.io/CommunitySolidServer/latest/usage/client-credentials/) +- [Inrupt — Authentication for Single-User Applications](https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/authenticate-nodejs-script/) +- [`@inrupt/solid-client-authn-node` API reference](https://inrupt.github.io/solid-client-authn-js/node/classes/Session.html) +- [Solid-OIDC specification](https://solid.github.io/solid-oidc/) diff --git a/docs/index.md b/docs/index.md index c4b082e..959818c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,10 @@ -# Home +# Welcome to Solid Developer Documentation + +Welcome! This site provides guides and resources to help you start building applications with [Solid](https://solidproject.org/) — the open standard that gives people control over their data. Whether you're creating your first Solid app or integrating Solid into an existing project, you'll find step-by-step tutorials to get you going. ## Guides - [Building your first Solid App with LDO & React](guides/building_your_first_solid_app_with_ldo_and_react) +- [Authenticating with a Node.js Script](guides/authenticating_with_a_script) - [Demo Application using Solid + Next.js + LDO](guides/solid_nextjs_ldo_demo_application) - [Hosting the Community Solid Server in an Azure App Service](guides/hosting_the_community_solid_server_in_an_azure_app_service) From a3af9a0bc4ec2e0f842399bbebdc802b76e2c00a Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sun, 15 Feb 2026 20:59:02 +0000 Subject: [PATCH 2/6] Update docs/guides/authenticating_with_a_script.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/guides/authenticating_with_a_script.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/authenticating_with_a_script.md b/docs/guides/authenticating_with_a_script.md index f07e3da..74c8b2d 100644 --- a/docs/guides/authenticating_with_a_script.md +++ b/docs/guides/authenticating_with_a_script.md @@ -20,7 +20,7 @@ The flow has three stages: ## 1. Set Up the Project -Create a new directory and initialise it: +Create a new directory and initialize it: ```bash mkdir solid-script && cd solid-script From 23adeec806665ccebcc720c8def871ac4059b1ce Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 21:38:00 +0000 Subject: [PATCH 3/6] feat: add guide for authenticating with a script (#15) * Initial plan * Address review feedback: load OIDC_ISSUER from env var, add cross-platform instructions Co-authored-by: jeswr <63333554+jeswr@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jeswr <63333554+jeswr@users.noreply.github.com> --- docs/guides/authenticating_with_a_script.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/guides/authenticating_with_a_script.md b/docs/guides/authenticating_with_a_script.md index 74c8b2d..8b9880d 100644 --- a/docs/guides/authenticating_with_a_script.md +++ b/docs/guides/authenticating_with_a_script.md @@ -72,7 +72,7 @@ import { Session } from '@inrupt/solid-client-authn-node'; // In production, load these from environment variables. const CLIENT_ID = process.env.SOLID_CLIENT_ID; const CLIENT_SECRET = process.env.SOLID_CLIENT_SECRET; -const OIDC_ISSUER = 'http://localhost:3000'; // Your Solid server URL +const OIDC_ISSUER = process.env.SOLID_OIDC_ISSUER; // Your Solid server URL async function main() { // Create a new session and log in @@ -102,14 +102,28 @@ async function main() { main().catch(console.error); ``` -Run the script: +Run the script, passing your credentials and server URL as environment variables. + +On **Linux / macOS** (Bash): ```bash SOLID_CLIENT_ID="your-client-id" \ SOLID_CLIENT_SECRET="your-client-secret" \ +SOLID_OIDC_ISSUER="http://localhost:3000" \ +node index.js +``` + +On **Windows** (PowerShell): + +```powershell +$env:SOLID_CLIENT_ID="your-client-id" +$env:SOLID_CLIENT_SECRET="your-client-secret" +$env:SOLID_OIDC_ISSUER="http://localhost:3000" node index.js ``` +Replace `http://localhost:3000` with the URL of your Solid server (for example, `https://solidcommunity.net` or `https://login.inrupt.com`). + You should see your profile document printed to the console. ## Tips From aa18836d63f5fb66a5ffcd2370e600b38e077d8d Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sat, 21 Feb 2026 18:18:53 +0000 Subject: [PATCH 4/6] Apply suggestions from code review Co-authored-by: Samu Lang --- docs/guides/authenticating_with_a_script.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/authenticating_with_a_script.md b/docs/guides/authenticating_with_a_script.md index 8b9880d..4a6c55b 100644 --- a/docs/guides/authenticating_with_a_script.md +++ b/docs/guides/authenticating_with_a_script.md @@ -102,7 +102,7 @@ async function main() { main().catch(console.error); ``` -Run the script, passing your credentials and server URL as environment variables. +Run the script, passing your credentials and authorization server URL (sometimes same as Solid server URL) as environment variables. On **Linux / macOS** (Bash): From 7259b999eea11510f37024b3c0d2ce06456bd883 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sat, 21 Feb 2026 18:19:20 +0000 Subject: [PATCH 5/6] Update docs/guides/authenticating_with_a_script.md Co-authored-by: Samu Lang --- docs/guides/authenticating_with_a_script.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/authenticating_with_a_script.md b/docs/guides/authenticating_with_a_script.md index 4a6c55b..a55e2cf 100644 --- a/docs/guides/authenticating_with_a_script.md +++ b/docs/guides/authenticating_with_a_script.md @@ -72,7 +72,7 @@ import { Session } from '@inrupt/solid-client-authn-node'; // In production, load these from environment variables. const CLIENT_ID = process.env.SOLID_CLIENT_ID; const CLIENT_SECRET = process.env.SOLID_CLIENT_SECRET; -const OIDC_ISSUER = process.env.SOLID_OIDC_ISSUER; // Your Solid server URL +const OIDC_ISSUER = process.env.SOLID_OIDC_ISSUER; // Your authorization server URL (sometimes called IdP, sometimes same as your Solid server URL) async function main() { // Create a new session and log in From bef5a91789e5c5c4b5c674244eca4160fd0620aa Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:49:49 +0000 Subject: [PATCH 6/6] fix: use optional SOLID_RESOURCE_URL for authenticated fetch example (#16) * Initial plan * fix: add optional SOLID_RESOURCE_URL env var for the resource to fetch Co-authored-by: jeswr <63333554+jeswr@users.noreply.github.com> * Apply suggestions from code review --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jeswr <63333554+jeswr@users.noreply.github.com> --- docs/guides/authenticating_with_a_script.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/guides/authenticating_with_a_script.md b/docs/guides/authenticating_with_a_script.md index a55e2cf..d8c0017 100644 --- a/docs/guides/authenticating_with_a_script.md +++ b/docs/guides/authenticating_with_a_script.md @@ -73,6 +73,7 @@ import { Session } from '@inrupt/solid-client-authn-node'; const CLIENT_ID = process.env.SOLID_CLIENT_ID; const CLIENT_SECRET = process.env.SOLID_CLIENT_SECRET; const OIDC_ISSUER = process.env.SOLID_OIDC_ISSUER; // Your authorization server URL (sometimes called IdP, sometimes same as your Solid server URL) +const RESOURCE_URL = process.env.SOLID_RESOURCE_URL; // URL of the protected resource to fetch (optional) async function main() { // Create a new session and log in @@ -90,8 +91,9 @@ async function main() { // session.fetch works just like the standard fetch API, // but automatically includes authentication headers. - const response = await session.fetch(session.info.webId); - console.log(`GET ${session.info.webId} — ${response.status}`); + const resourceUrl = RESOURCE_URL ?? session.info.webId; + const response = await session.fetch(resourceUrl); + console.log(`GET ${resourceUrl} — ${response.status}`); console.log(await response.text()); // Always log out when done @@ -102,7 +104,7 @@ async function main() { main().catch(console.error); ``` -Run the script, passing your credentials and authorization server URL (sometimes same as Solid server URL) as environment variables. +Run the script, passing your credentials, authorization server URL (sometimes same as Solid server URL), and optionally the URL of the protected resource you want to fetch as environment variables. On **Linux / macOS** (Bash): @@ -110,6 +112,7 @@ On **Linux / macOS** (Bash): SOLID_CLIENT_ID="your-client-id" \ SOLID_CLIENT_SECRET="your-client-secret" \ SOLID_OIDC_ISSUER="http://localhost:3000" \ +SOLID_RESOURCE_URL="http://localhost:3000/your-pod/private-resource" \ node index.js ``` @@ -119,12 +122,13 @@ On **Windows** (PowerShell): $env:SOLID_CLIENT_ID="your-client-id" $env:SOLID_CLIENT_SECRET="your-client-secret" $env:SOLID_OIDC_ISSUER="http://localhost:3000" +$env:SOLID_RESOURCE_URL="http://localhost:3000/your-pod/private-resource" node index.js ``` -Replace `http://localhost:3000` with the URL of your Solid server (for example, `https://solidcommunity.net` or `https://login.inrupt.com`). +Replace `http://localhost:3000` with the URL of your authorization server (for example, `https://solidcommunity.net` or `https://login.inrupt.com`), and set `SOLID_RESOURCE_URL` to the URL of the private resource you want to access. If `SOLID_RESOURCE_URL` is omitted, the script falls back to fetching your WebID profile document. -You should see your profile document printed to the console. +You should see the contents of the resource printed to the console. ## Tips