Skip to content

Commit

Permalink
Update Community Solid Server to v7 (#12)
Browse files Browse the repository at this point in the history
Also move account creation and authentication from 'src/helpers' to package 'css-authn'
https://www.npmjs.com/package/css-authn
  • Loading branch information
mrkvon committed Jan 13, 2024
1 parent 66af5fb commit 96238a1
Show file tree
Hide file tree
Showing 13 changed files with 2,616 additions and 2,794 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18

- name: Install NPM packages
run: yarn install --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18

- name: Checkout
uses: actions/checkout@v3
Expand Down
12 changes: 10 additions & 2 deletions experimental-pod-seed.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
[
{ "podName": "bot", "email": "bot@example", "password": "password" },
{ "podName": "person", "email": "person@example", "password": "password" }
{
"email": "bot@example",
"password": "password",
"pods": [{ "name": "bot" }]
},
{
"email": "person@example",
"password": "password",
"pods": [{ "name": "person" }]
}
]
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"license": "MIT",
"devDependencies": {
"@solid/community-server": "^6.0.1",
"@solid/community-server": "^7.0.2",
"@types/bcryptjs": "^2.4.2",
"@types/chai": "^4.3.5",
"@types/co-body": "^6.1.0",
Expand All @@ -27,6 +27,7 @@
"@types/nodemailer": "^6.4.9",
"@types/parse-link-header": "^2.0.1",
"@types/sinon": "^10.0.15",
"@types/tough-cookie": "^4.0.5",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"chai": "^4.3.7",
Expand All @@ -40,6 +41,7 @@
"rdf-namespaces": "^1.11.0",
"sinon": "^15.2.0",
"swagger-autogen": "^2.23.6",
"tough-cookie": "^4.1.3",
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
},
Expand All @@ -53,6 +55,7 @@
"ajv-formats": "^2.1.1",
"bcryptjs": "^2.4.3",
"cross-fetch": "^4.0.0",
"css-authn": "^0.0.14",
"dotenv": "^16.0.0",
"koa": "^2.14.2",
"koa-helmet": "^7.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const baseUrl = process.env.BASE_URL ?? 'http://localhost:3005'
export const mailerCredentials = {
email: process.env.MAILER_IDENTITY_EMAIL ?? 'bot@example',
password: process.env.MAILER_IDENTITY_PASSWORD ?? 'password',
solidServer: process.env.MAILER_IDENTITY_PROVIDER ?? 'http://localhost:3456',
provider: process.env.MAILER_IDENTITY_PROVIDER ?? 'http://localhost:3456',
}

const stringToBoolean = (value: string | undefined): boolean => {
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/integration.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { compare, hash } from 'bcryptjs'
import fetch from 'cross-fetch'
import crypto from 'crypto'
import { getAuthenticatedFetch } from 'css-authn/dist/7.x'
import { Middleware } from 'koa'
import { pick } from 'lodash'
import n3 from 'n3'
import parseLinkHeader from 'parse-link-header'
import * as config from '../config'
import { EmailVerification, Integration } from '../config/sequelize'
import { getAuthenticatedFetch } from '../helpers'
import { sendMail } from '../services/mailerService'

export const initializeIntegration: Middleware = async ctx => {
Expand Down
104 changes: 2 additions & 102 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,106 +1,6 @@
import {
buildAuthenticatedFetch,
createDpopHeader,
generateDpopKeyPair,
} from '@inrupt/solid-client-authn-core'
import { expect } from 'chai'
import fetch from 'cross-fetch'
import { createAccount } from 'css-authn/dist/7.x'
import * as uuid from 'uuid'

type Credentials = { email: string; password: string }

export const getAuthenticatedFetch = async ({
email,
password,
solidServer,
}: Credentials & { solidServer: string }) => {
const response = await fetch(`${solidServer}/idp/credentials/`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
// The email/password fields are those of your account.
// The name field will be used when generating the ID of your token.
body: JSON.stringify({ email, password, name: 'token' }),
})

const { id, secret } = await response.json()

const dpopKey = await generateDpopKeyPair()

// These are the ID and secret generated in the previous step.
// Both the ID and the secret need to be form-encoded.
const authString = `${encodeURIComponent(id)}:${encodeURIComponent(secret)}`
// This URL can be found by looking at the "token_endpoint" field at
// http://localhost:3000/.well-known/openid-configuration
// if your server is hosted at http://localhost:3000/.
const tokenUrl = `${solidServer}/.oidc/token`
const response2 = await fetch(tokenUrl, {
method: 'POST',
headers: {
// The header needs to be in base64 encoding.
authorization: `Basic ${Buffer.from(authString).toString('base64')}`,
'content-type': 'application/x-www-form-urlencoded',
dpop: await createDpopHeader(tokenUrl, 'POST', dpopKey),
},
body: 'grant_type=client_credentials&scope=webid',
})

// This is the Access token that will be used to do an authenticated request to the server.
// The JSON also contains an "expires_in" field in seconds,
// which you can use to know when you need request a new Access token.
const { access_token: accessToken } = await response2.json()

// The DPoP key needs to be the same key as the one used in the previous step.
// The Access token is the one generated in the previous step.
const authFetch = await buildAuthenticatedFetch(fetch, accessToken, {
dpopKey,
})
// authFetch can now be used as a standard fetch function that will authenticate as your WebID.

return authFetch
}

export const createAccount = async ({
username,
password,
email,
solidServer,
}: {
username: string
password?: string
email?: string
solidServer: string
}) => {
password ??= 'correcthorsebatterystaple'
email ??= username + '@example.org'
const config = {
idp: solidServer + '/',
podUrl: `${solidServer}/${username}/`,
webId: `${solidServer}/${username}/profile/card#me`,
username,
password,
email,
}
const registerEndpoint = solidServer + '/idp/register/'
const response = await fetch(registerEndpoint, {
method: 'post',
body: JSON.stringify({
email,
password,
confirmPassword: password,
createWebId: true,
register: true,
createPod: true,
rootPod: false,
podName: username,
}),
headers: { 'content-type': 'application/json' },
})

expect(response.ok).to.be.true

return config
}

export const createRandomAccount = ({
solidServer,
}: {
Expand All @@ -110,6 +10,6 @@ export const createRandomAccount = ({
username: uuid.v4(),
password: uuid.v4(),
email: uuid.v4() + '@example.com',
solidServer,
provider: solidServer,
})
}
8 changes: 4 additions & 4 deletions src/test/css-config-no-notifications.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^6.0.0/components/context.jsonld",
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
"import": [
"css:config/app/init/initialize-intro.json",
"css:config/app/main/default.json",
"css:config/app/init/initialize-prefilled-root.json",
"css:config/app/setup/optional.json",
"css:config/app/variables/default.json",
"css:config/http/handler/default.json",
"css:config/http/middleware/default.json",
Expand All @@ -13,9 +12,9 @@
"css:config/identity/access/public.json",
"css:config/identity/email/default.json",
"css:config/identity/handler/default.json",
"css:config/identity/oidc/default.json",
"css:config/identity/ownership/token.json",
"css:config/identity/pod/static.json",
"css:config/identity/registration/enabled.json",
"css:config/ldp/authentication/dpop-bearer.json",
"css:config/ldp/authorization/webacl.json",
"css:config/ldp/handler/default.json",
Expand All @@ -24,6 +23,7 @@
"css:config/ldp/modes/default.json",
"css:config/storage/backend/memory.json",
"css:config/storage/key-value/resource-store.json",
"css:config/storage/location/root.json",
"css:config/storage/middleware/default.json",
"css:config/util/auxiliary/acl.json",
"css:config/util/identifiers/suffix.json",
Expand Down
8 changes: 4 additions & 4 deletions src/test/css-default-config.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^6.0.0/components/context.jsonld",
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
"import": [
"css:config/app/init/initialize-intro.json",
"css:config/app/main/default.json",
"css:config/app/init/initialize-prefilled-root.json",
"css:config/app/setup/optional.json",
"css:config/app/variables/default.json",
"css:config/http/handler/default.json",
"css:config/http/middleware/default.json",
Expand All @@ -13,9 +12,9 @@
"css:config/identity/access/public.json",
"css:config/identity/email/default.json",
"css:config/identity/handler/default.json",
"css:config/identity/oidc/default.json",
"css:config/identity/ownership/token.json",
"css:config/identity/pod/static.json",
"css:config/identity/registration/enabled.json",
"css:config/ldp/authentication/dpop-bearer.json",
"css:config/ldp/authorization/webacl.json",
"css:config/ldp/handler/default.json",
Expand All @@ -24,6 +23,7 @@
"css:config/ldp/modes/default.json",
"css:config/storage/backend/memory.json",
"css:config/storage/key-value/resource-store.json",
"css:config/storage/location/root.json",
"css:config/storage/middleware/default.json",
"css:config/util/auxiliary/acl.json",
"css:config/util/identifiers/suffix.json",
Expand Down
18 changes: 15 additions & 3 deletions src/test/css-pod-seed.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
[
{ "podName": "bot", "email": "bot@example", "password": "password" },
{ "podName": "person", "email": "person@example", "password": "password" },
{ "podName": "person2", "email": "person2@example", "password": "password" }
{
"email": "bot@example",
"password": "password",
"pods": [{ "name": "bot" }]
},
{
"email": "person@example",
"password": "password",
"pods": [{ "name": "person" }]
},
{
"email": "person2@example",
"password": "password",
"pods": [{ "name": "person2" }]
}
]
4 changes: 2 additions & 2 deletions src/test/notification.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { expect } from 'chai'
import * as cheerio from 'cheerio'
import fetch from 'cross-fetch'
import { getAuthenticatedFetch } from 'css-authn/dist/7.x'
import { describe } from 'mocha'
import Mail from 'nodemailer/lib/mailer'
import { SinonSandbox, SinonSpy, createSandbox } from 'sinon'
import { promisify } from 'util'
import { baseUrl } from '../config'
import { getAuthenticatedFetch } from '../helpers'
import * as mailerService from '../services/mailerService'
import { addRead, setupInbox } from '../setup'
import { authenticatedFetch, person } from './testSetup.spec'
Expand Down Expand Up @@ -76,7 +76,7 @@ describe('received notification via /webhook-receiver', () => {
const authenticatedPerson2Fetch = await getAuthenticatedFetch({
email: 'person2@example',
password: 'password',
solidServer: 'http://localhost:3456',
provider: 'http://localhost:3456',
})
const addToInboxResponse = await authenticatedPerson2Fetch(
person.podUrl + 'inbox/',
Expand Down
Loading

0 comments on commit 96238a1

Please sign in to comment.