solid-server 5.8.8-8d509db1 → 5.8.8-a4d2fc6d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/common/js/auth-buttons.mjs +20 -20
  2. package/common/js/index-buttons.mjs +30 -30
  3. package/common/js/solid.mjs +11 -11
  4. package/config/defaults.mjs +1 -1
  5. package/coverage/tmp/coverage-2270-1767346136095-0.json +1 -0
  6. package/coverage/tmp/{coverage-2255-1766613179053-0.json → coverage-2271-1767346114541-0.json} +1 -1
  7. package/eslint.config.mjs +102 -0
  8. package/index.mjs +8 -8
  9. package/lib/acl-checker.mjs +0 -1
  10. package/lib/handlers/copy.mjs +0 -2
  11. package/lib/handlers/cors-proxy.mjs +0 -2
  12. package/lib/handlers/get.mjs +2 -2
  13. package/lib/handlers/index.mjs +0 -2
  14. package/lib/handlers/options.mjs +0 -2
  15. package/lib/ldp.mjs +0 -2
  16. package/lib/models/oidc-manager.mjs +0 -1
  17. package/lib/resource-mapper.mjs +1 -3
  18. package/lib/utils.mjs +0 -2
  19. package/lib/webid/tls/index.mjs +0 -1
  20. package/package.json +26 -24
  21. package/solid-server-5.8.8.tgz +0 -0
  22. package/test/integration/account-manager-test.mjs +0 -1
  23. package/test/integration/account-template-test.mjs +0 -1
  24. package/test/integration/authentication-oidc-test.mjs +1 -1
  25. package/test/integration/capability-discovery-test.mjs +0 -1
  26. package/test/integration/oidc-manager-test.mjs +95 -2
  27. package/test/integration/patch-test.mjs +29 -12
  28. package/test/integration/quota-test.mjs +0 -1
  29. package/test/integration/www-account-creation-oidc-test.mjs +0 -1
  30. package/test/resources/accounts/db/oidc/op/clients/{_key_30860bb5cf6ba07e80ed7b2e7178c7ad.json → _key_e989e9f58cf29869c56a68ceb4256b69.json} +1 -1
  31. package/test/resources/accounts/db/oidc/op/provider.json +345 -1
  32. package/test/resources/accounts/db/oidc/rp/clients/_key_https%3A%2F%2Flocalhost%3A3457.json +1 -1
  33. package/test/resources/accounts-acl/db/oidc/op/provider.json +345 -1
  34. package/test/resources/accounts-scenario/alice/db/oidc/op/clients/{_key_e46bcfe080c59f5cbb53a559d6a272cb.json → _key_a31de046443144df66179553447ffed2.json} +1 -1
  35. package/test/resources/accounts-scenario/alice/db/oidc/op/provider.json +345 -1
  36. package/test/resources/accounts-scenario/alice/db/oidc/rp/clients/_key_https%3A%2F%2Flocalhost%3A7000.json +1 -1
  37. package/test/resources/accounts-scenario/bob/db/oidc/op/clients/{_key_e7fd102ec26a3dcd5916751e01a62315.json → _key_cf92a9f132c1973db4163b653050ac5f.json} +1 -1
  38. package/test/resources/accounts-scenario/bob/db/oidc/op/provider.json +345 -1
  39. package/test/resources/accounts-scenario/bob/db/oidc/rp/clients/_key_https%3A%2F%2Flocalhost%3A7001.json +1 -1
  40. package/test/resources/accounts-scenario/charlie/db/oidc/op/clients/{_key_0eec962830f849876695b69df76a3137.json → _key_25fe3c0bf640a75aecd0ccb1c2951eb1.json} +1 -1
  41. package/test/resources/accounts-scenario/charlie/db/oidc/op/provider.json +345 -1
  42. package/test/resources/accounts-scenario/charlie/db/oidc/rp/clients/_key_https%3A%2F%2Flocalhost%3A5002.json +1 -1
  43. package/test/resources/accounts-strict-origin-off/alice/db/oidc/op/clients/{_key_7d536a1f8c6eb86f41261e171a8af79a.json → _key_1a5ed3aa47de01ee7438f2537e1b5331.json} +1 -1
  44. package/test/resources/accounts-strict-origin-off/alice/db/oidc/op/provider.json +345 -1
  45. package/test/resources/accounts-strict-origin-off/alice/db/oidc/rp/clients/_key_https%3A%2F%2Flocalhost%3A7010.json +1 -1
  46. package/test/resources/accounts-strict-origin-off/bob/db/oidc/op/clients/{_key_0ed30b9e076814c6f6445582302487c2.json → _key_30b67c31ec6753bde889bbb157e879c5.json} +1 -1
  47. package/test/resources/accounts-strict-origin-off/bob/db/oidc/op/provider.json +345 -1
  48. package/test/resources/accounts-strict-origin-off/bob/db/oidc/rp/clients/_key_https%3A%2F%2Flocalhost%3A7011.json +1 -1
  49. package/test/unit/account-template-test.mjs +0 -1
  50. package/test/unit/add-cert-request-test.mjs +0 -1
  51. package/test/unit/email-service-test.mjs +0 -1
  52. package/test/unit/email-welcome-test.mjs +0 -1
  53. package/test/unit/esm-imports.test.mjs +0 -1
  54. package/test/unit/oidc-manager-test.mjs +0 -1
  55. package/test/unit/solid-host-test.mjs +0 -1
  56. package/test/unit/user-account-test.mjs +0 -1
  57. package/test/validate-turtle.mjs +0 -1
  58. package/coverage/tmp/coverage-2254-1766613200322-0.json +0 -1
@@ -0,0 +1,102 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+
4
+ export default [
5
+ js.configs.recommended,
6
+ {
7
+ languageOptions: {
8
+ ecmaVersion: 2022,
9
+ sourceType: 'module',
10
+ globals: {
11
+ ...globals.node,
12
+ ...globals.mocha,
13
+ fetch: 'readonly',
14
+ AbortController: 'readonly',
15
+ Headers: 'readonly',
16
+ Request: 'readonly',
17
+ Response: 'readonly',
18
+ URL: 'readonly',
19
+ URLSearchParams: 'readonly'
20
+ }
21
+ },
22
+ rules: {
23
+ // StandardJS-like rules
24
+ 'no-unused-vars': ['error', {
25
+ args: 'none',
26
+ caughtErrors: 'none',
27
+ ignoreRestSiblings: true,
28
+ vars: 'all'
29
+ }],
30
+ 'no-empty': ['error', { allowEmptyCatch: true }],
31
+ 'no-var': 'error',
32
+ 'prefer-const': ['error', { destructuring: 'all' }],
33
+ 'quote-props': ['error', 'as-needed'],
34
+ semi: ['error', 'never'],
35
+ quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: true }],
36
+ 'comma-dangle': ['error', 'never'],
37
+ 'space-before-function-paren': ['error', 'always'],
38
+ indent: ['error', 2, {
39
+ SwitchCase: 1,
40
+ VariableDeclarator: 1,
41
+ outerIIFEBody: 1,
42
+ MemberExpression: 1,
43
+ FunctionDeclaration: { parameters: 1, body: 1 },
44
+ FunctionExpression: { parameters: 1, body: 1 },
45
+ CallExpression: { arguments: 1 },
46
+ ArrayExpression: 1,
47
+ ObjectExpression: 1,
48
+ ImportDeclaration: 1,
49
+ flatTernaryExpressions: false,
50
+ ignoreComments: false,
51
+ ignoredNodes: ['TemplateLiteral *', 'JSXElement', 'JSXElement > *', 'JSXAttribute', 'JSXIdentifier', 'JSXNamespacedName', 'JSXMemberExpression', 'JSXSpreadAttribute', 'JSXExpressionContainer', 'JSXOpeningElement', 'JSXClosingElement', 'JSXFragment', 'JSXOpeningFragment', 'JSXClosingFragment', 'JSXText', 'JSXEmptyExpression', 'JSXSpreadChild'],
52
+ offsetTernaryExpressions: true
53
+ }],
54
+ 'key-spacing': ['error', { beforeColon: false, afterColon: true }],
55
+ 'keyword-spacing': ['error', { before: true, after: true }],
56
+ 'object-curly-spacing': ['error', 'always'],
57
+ 'array-bracket-spacing': ['error', 'never'],
58
+ 'space-in-parens': ['error', 'never'],
59
+ 'space-before-blocks': ['error', 'always'],
60
+ 'space-infix-ops': 'error',
61
+ 'eol-last': 'error',
62
+ 'no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 0 }],
63
+ 'no-trailing-spaces': 'error',
64
+ 'comma-spacing': ['error', { before: false, after: true }],
65
+ 'no-multi-spaces': 'error',
66
+ 'no-mixed-operators': ['error', {
67
+ groups: [
68
+ ['==', '!=', '===', '!==', '>', '>=', '<', '<='],
69
+ ['&&', '||'],
70
+ ['in', 'instanceof']
71
+ ],
72
+ allowSamePrecedence: true
73
+ }],
74
+ 'operator-linebreak': ['error', 'after', { overrides: { '?': 'before', ':': 'before', '|>': 'before' } }],
75
+ 'brace-style': ['error', '1tbs', { allowSingleLine: true }],
76
+ 'arrow-spacing': ['error', { before: true, after: true }],
77
+ 'padded-blocks': ['error', { blocks: 'never', switches: 'never', classes: 'never' }],
78
+ 'no-use-before-define': ['error', { functions: false, classes: false, variables: false }]
79
+ }
80
+ },
81
+ {
82
+ // Browser files (client-side code)
83
+ files: ['common/**/*.mjs'],
84
+ languageOptions: {
85
+ globals: {
86
+ ...globals.browser,
87
+ solid: 'readonly',
88
+ UI: 'readonly',
89
+ owaspPasswordStrengthTest: 'readonly'
90
+ }
91
+ }
92
+ },
93
+ {
94
+ ignores: [
95
+ 'node_modules/**',
96
+ 'coverage/**',
97
+ '.db/**',
98
+ 'data/**',
99
+ 'resources/**'
100
+ ]
101
+ }
102
+ ]
package/index.mjs CHANGED
@@ -8,15 +8,15 @@ import startCli from './bin/lib/cli.mjs'
8
8
  let exported
9
9
  const canAttach = (ldnode && (typeof ldnode === 'object' || typeof ldnode === 'function'))
10
10
  if (canAttach) {
11
- try {
12
- if (!ldnode.createServer) ldnode.createServer = createServer
13
- if (!ldnode.startCli) ldnode.startCli = startCli
14
- exported = ldnode
15
- } catch (e) {
16
- exported = { default: ldnode, createServer, startCli }
17
- }
11
+ try {
12
+ if (!ldnode.createServer) ldnode.createServer = createServer
13
+ if (!ldnode.startCli) ldnode.startCli = startCli
14
+ exported = ldnode
15
+ } catch (e) {
16
+ exported = { default: ldnode, createServer, startCli }
17
+ }
18
18
  } else {
19
- exported = { default: ldnode, createServer, startCli }
19
+ exported = { default: ldnode, createServer, startCli }
20
20
  }
21
21
 
22
22
  export default exported
@@ -1,5 +1,4 @@
1
1
  'use strict'
2
- /* eslint-disable node/no-deprecated-api */
3
2
 
4
3
  import { dirname } from 'path'
5
4
  import rdf from 'rdflib'
@@ -1,5 +1,3 @@
1
- /* eslint-disable node/no-deprecated-api */
2
-
3
1
  import debug from '../debug.mjs'
4
2
  import HTTPError from '../http-error.mjs'
5
3
  import ldpCopy from '../ldp-copy.mjs'
@@ -1,5 +1,3 @@
1
- /* eslint-disable node/no-deprecated-api */
2
-
3
1
  import { createProxyMiddleware } from 'http-proxy-middleware'
4
2
  import cors from 'cors'
5
3
  import debug from '../debug.mjs'
@@ -240,7 +240,7 @@ function hasReadPermissions (file, req, res, callback) {
240
240
  if (!ldp.webid) {
241
241
  // FIXME: what is the rule that causes
242
242
  // "Unexpected literal in error position of callback" in `npm run standard`?
243
- // eslint-disable-next-line
243
+
244
244
  return callback(true)
245
245
  }
246
246
 
@@ -249,6 +249,6 @@ function hasReadPermissions (file, req, res, callback) {
249
249
  res.locals.path = relativePath
250
250
  // FIXME: what is the rule that causes
251
251
  // "Unexpected literal in error position of callback" in `npm run standard`?
252
- // eslint-disable-next-line
252
+
253
253
  allow('Read')(req, res, err => callback(!err))
254
254
  }
@@ -1,5 +1,3 @@
1
- /* eslint-disable node/no-deprecated-api */
2
-
3
1
  import path from 'path'
4
2
  import debugModule from 'debug'
5
3
  import Negotiator from 'negotiator'
@@ -1,5 +1,3 @@
1
- /* eslint-disable node/no-deprecated-api */
2
-
3
1
  import { addLink } from '../header.mjs'
4
2
  import url from 'url'
5
3
 
package/lib/ldp.mjs CHANGED
@@ -1,5 +1,3 @@
1
- /* eslint-disable node/no-deprecated-api */
2
-
3
1
  import utilPath, { join, dirname } from 'path'
4
2
  import intoStream from 'into-stream'
5
3
  import urlModule from 'url'
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-unused-expressions */
2
1
  import { URL } from 'url'
3
2
  import path from 'path'
4
3
  import debug from '../debug.mjs'
@@ -1,5 +1,3 @@
1
- /* eslint-disable node/no-deprecated-api, no-mixed-operators */
2
-
3
1
  import fs from 'fs'
4
2
  import URL from 'url'
5
3
  import { promisify } from 'util'
@@ -196,7 +194,7 @@ class ResourceMapper {
196
194
  _getContentTypeFromExtension (path) {
197
195
  const defaultContentType = (path === '' || path.endsWith('/')) ? this._defaultContainerContentType : this._defaultContentType
198
196
  const extension = /\.([^/.]+)$/.exec(path)
199
- return extension && this._types[extension[1].toLowerCase()] || defaultContentType
197
+ return (extension && this._types[extension[1].toLowerCase()]) || defaultContentType
200
198
  }
201
199
 
202
200
  // Appends an extension for the specific content type, if needed
package/lib/utils.mjs CHANGED
@@ -1,5 +1,3 @@
1
- /* eslint-disable node/no-deprecated-api */
2
-
3
1
  import fs from 'fs'
4
2
  import path from 'path'
5
3
  import util from 'util'
@@ -1,4 +1,3 @@
1
-
2
1
  import * as verifyModule from '../lib/verify.mjs'
3
2
  import * as generateModule from './generate.mjs'
4
3
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "solid-server",
3
3
  "description": "Solid server on top of the file-system",
4
- "version": "5.8.8-8d509db1",
4
+ "version": "5.8.8-a4d2fc6d",
5
5
  "author": {
6
6
  "name": "Tim Berners-Lee",
7
7
  "email": "timbl@w3.org"
@@ -62,25 +62,27 @@
62
62
  "@fastify/busboy": "^1.2.1",
63
63
  "@fastify/pre-commit": "^2.2.1",
64
64
  "@solid/acl-check": "^0.4.5",
65
- "@solid/oidc-auth-manager": "^0.24.5",
66
- "@solid/oidc-op": "^0.11.7",
67
- "@solid/oidc-rp": "^0.11.8",
65
+ "@solid/oidc-auth-manager": "^0.25.1",
66
+ "@solid/oidc-op": "^0.12.1",
67
+ "@solid/oidc-rp": "^0.12.0",
68
+ "@solid/solid-multi-rp-client": "^0.7.0",
68
69
  "async-lock": "^1.4.1",
69
- "body-parser": "^1.20.3",
70
+ "body-parser": "^1.20.4",
70
71
  "bootstrap": "^3.4.1",
71
72
  "cached-path-relative": "^1.1.0",
72
73
  "camelize": "^1.0.1",
73
- "cheerio": "^1.0.0",
74
+ "cheerio": "^1.1.2",
74
75
  "colorette": "^2.0.20",
75
76
  "commander": "^8.3.0",
76
77
  "cors": "^2.8.5",
77
78
  "debug": "^4.4.3",
78
- "express": "^4.21.2",
79
+ "eslint": "^9.39.2",
80
+ "express": "^4.22.1",
79
81
  "express-accept-events": "^0.3.0",
80
82
  "express-handlebars": "^5.3.5",
81
83
  "express-negotiate-events": "^0.3.0",
82
84
  "express-prep": "^0.6.4",
83
- "express-session": "^1.18.1",
85
+ "express-session": "^1.18.2",
84
86
  "extend": "^3.0.2",
85
87
  "from2": "^2.3.0",
86
88
  "fs-extra": "^10.1.0",
@@ -88,8 +90,8 @@
88
90
  "glob": "^7.2.3",
89
91
  "global-tunnel-ng": "^2.7.1",
90
92
  "handlebars": "^4.7.8",
91
- "http-proxy-middleware": "^2.0.7",
92
- "inquirer": "^8.2.6",
93
+ "http-proxy-middleware": "^2.0.9",
94
+ "inquirer": "^8.2.7",
93
95
  "into-stream": "^5.1.1",
94
96
  "ip-range-check": "0.2.0",
95
97
  "is-ip": "^2.0.0",
@@ -98,12 +100,12 @@
98
100
  "mime-types": "^2.1.35",
99
101
  "negotiator": "^0.6.4",
100
102
  "node-fetch": "^2.7.0",
101
- "node-forge": "^1.3.2",
103
+ "node-forge": "^1.3.3",
102
104
  "node-mailer": "^0.1.1",
103
- "nodemailer": "^7.0.10",
105
+ "nodemailer": "^7.0.12",
104
106
  "oidc-op-express": "^0.0.3",
105
107
  "owasp-password-strength-test": "^1.3.0",
106
- "rdflib": "^2.3.0",
108
+ "rdflib": "^2.3.2",
107
109
  "recursive-readdir": "^2.2.3",
108
110
  "rimraf": "^3.0.2",
109
111
  "solid-auth-client": "^2.5.6",
@@ -111,38 +113,38 @@
111
113
  "solid-ws": "^0.4.3",
112
114
  "text-encoder-lite": "^2.0.0",
113
115
  "the-big-username-blacklist": "^1.5.2",
114
- "ulid": "^2.3.0",
116
+ "ulid": "^2.4.0",
115
117
  "urijs": "^1.19.11",
116
118
  "uuid": "^13.0.0",
117
119
  "valid-url": "^1.0.9",
118
- "validator": "^13.12.0",
120
+ "validator": "^13.15.26",
119
121
  "vhost": "^3.0.2"
120
122
  },
121
123
  "devDependencies": {
122
124
  "@cxres/structured-headers": "^2.0.0-nesting.0",
123
- "@solid/solid-auth-oidc": "^0.5.7",
125
+ "@eslint/js": "^9.39.2",
126
+ "@solid/solid-auth-oidc": "^0.6.0",
124
127
  "c8": "^10.1.3",
125
128
  "chai": "^4.5.0",
126
129
  "chai-as-promised": "7.1.2",
127
130
  "cross-env": "7.0.3",
128
131
  "dirty-chai": "2.0.1",
129
- "eslint": "^7.32.0",
132
+ "globals": "^17.0.0",
130
133
  "localstorage-memory": "1.0.3",
131
134
  "mocha": "^10.8.2",
132
135
  "nock": "^13.5.6",
133
- "node-mocks-http": "^1.16.2",
136
+ "node-mocks-http": "^1.17.2",
134
137
  "prep-fetch": "^0.1.0",
135
138
  "randombytes": "2.1.0",
136
139
  "sinon": "12.0.1",
137
140
  "sinon-chai": "3.7.0",
138
- "snyk": "^1.1295.3",
139
- "standard": "16.0.4",
141
+ "snyk": "^1.1301.2",
140
142
  "supertest": "^6.3.4",
141
143
  "turtle-validator": "1.1.1",
142
144
  "whatwg-url": "11.0.0"
143
145
  },
144
146
  "pre-commit": [
145
- "standard"
147
+ "lint"
146
148
  ],
147
149
  "main": "index.mjs",
148
150
  "exports": {
@@ -154,8 +156,8 @@
154
156
  "scripts": {
155
157
  "build": "echo nothing to build",
156
158
  "solid": "node ./bin/solid",
157
- "standard": "standard \"{bin,examples,lib,test}/**/*.mjs\"",
158
- "standard-fix": "standard --fix \"{bin,examples,lib,test}/**/*.mjs\"",
159
+ "lint": "eslint \"**/*.mjs\"",
160
+ "lint-fix": "eslint --fix \"**/*.mjs\"",
159
161
  "validate": "node ./test/validate-turtle.mjs",
160
162
  "c8": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 c8 --reporter=text-summary mocha --recursive test/unit/ test/integration/",
161
163
  "mocha": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --recursive test/unit/ test/integration/",
@@ -169,7 +171,7 @@
169
171
  "mocha-ldp": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --recursive test/integration/ldp-test.mjs",
170
172
  "ignore:prepublishOnly": "npm test",
171
173
  "ignore:postpublish": "git push --follow-tags",
172
- "test": "npm run standard && npm run validate && npm run c8",
174
+ "test": "npm run lint && npm run validate && npm run c8",
173
175
  "test-unit": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha test/unit/**/*.mjs --timeout 10000",
174
176
  "test-integration": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha test/integration/**/*.mjs --timeout 15000",
175
177
  "test-performance": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha test/performance/**/*.mjs --timeout 10000",
Binary file
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-unused-expressions */
2
1
  import path from 'path'
3
2
  import { fileURLToPath } from 'url'
4
3
  import fs from 'fs-extra'
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-unused-expressions */
2
1
  import { fileURLToPath } from 'url'
3
2
  import path from 'path'
4
3
  import fs from 'fs-extra'
@@ -26,7 +26,7 @@ const __dirname = path.dirname(__filename)
26
26
 
27
27
  // FIXME #1502
28
28
  describe('Authentication API (OIDC)', () => {
29
- let alice, bob // eslint-disable-line no-unused-vars
29
+ let alice, bob
30
30
 
31
31
  const aliceServerUri = 'https://localhost:7000'
32
32
  const aliceWebId = 'https://localhost:7000/profile/card#me'
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-unused-expressions */
2
1
  import { fileURLToPath } from 'url'
3
2
  import path from 'path'
4
3
  import supertest from 'supertest'
@@ -1,6 +1,6 @@
1
- /* eslint-disable no-unused-expressions */
2
1
  import { fileURLToPath } from 'url'
3
2
  import path from 'path'
3
+ import { URL } from 'url'
4
4
  import chai from 'chai'
5
5
  import fs from 'fs-extra'
6
6
  import { fromServerConfig } from '../../lib/models/oidc-manager.mjs'
@@ -38,5 +38,98 @@ describe('OidcManager', () => {
38
38
  expect(oidc.users.backend.path.endsWith('db/oidc/users'))
39
39
  expect(oidc.users.saltRounds).to.equal(saltRounds)
40
40
  })
41
+
42
+ it('should set the provider issuer which is used for iss claim in tokens', () => {
43
+ const providerUri = 'https://pivot-test.solidproject.org:8443'
44
+ const host = SolidHost.from({ serverUri: providerUri })
45
+
46
+ const saltRounds = 5
47
+ const argv = {
48
+ host,
49
+ dbPath,
50
+ saltRounds
51
+ }
52
+
53
+ const oidc = fromServerConfig(argv)
54
+
55
+ // Verify the issuer is set correctly for RFC 9207 compliance
56
+ // The iss claim in tokens should match this issuer value
57
+ expect(oidc.provider.issuer).to.exist
58
+ expect(oidc.provider.issuer).to.not.be.null
59
+ expect(oidc.provider.issuer).to.equal(providerUri)
60
+ console.log('Provider issuer (used for iss claim):', oidc.provider.issuer)
61
+ })
62
+ })
63
+
64
+ describe('RFC 9207 - Authorization redirect with iss parameter', () => {
65
+ it('should include iss parameter when redirecting after authorization', async () => {
66
+ const providerUri = 'https://localhost:8443'
67
+ const host = SolidHost.from({ providerUri })
68
+
69
+ const argv = {
70
+ host,
71
+ dbPath,
72
+ saltRounds: 5
73
+ }
74
+
75
+ const oidc = fromServerConfig(argv)
76
+
77
+ // Dynamically import BaseRequest from oidc-op
78
+ const { default: BaseRequest } = await import('@solid/oidc-op/src/handlers/BaseRequest.js')
79
+
80
+ // Create a mock request/response to test the redirect behavior
81
+ const mockReq = {
82
+ method: 'GET',
83
+ query: {
84
+ response_type: 'code',
85
+ redirect_uri: 'https://app.example.com/callback',
86
+ client_id: 'https://app.example.com',
87
+ state: 'test-state'
88
+ }
89
+ }
90
+
91
+ const mockRes = {
92
+ redirectCalled: false,
93
+ redirectUrl: '',
94
+ redirect (url) {
95
+ this.redirectCalled = true
96
+ this.redirectUrl = url
97
+ }
98
+ }
99
+
100
+ const request = new BaseRequest(mockReq, mockRes, oidc.provider)
101
+ request.params = mockReq.query
102
+
103
+ // Simulate a successful authorization by calling redirect with auth data
104
+ try {
105
+ request.redirect({ code: 'test-auth-code' })
106
+ } catch (err) {
107
+ // The redirect throws a HandledError, which is expected behavior
108
+ // We just need to check that the redirect was called with the right URL
109
+ }
110
+
111
+ expect(mockRes.redirectCalled).to.be.true
112
+ expect(mockRes.redirectUrl).to.exist
113
+
114
+ // Parse the redirect URL to check for iss parameter
115
+ const redirectUrl = new URL(mockRes.redirectUrl)
116
+
117
+ // The iss parameter can be in either the query string or hash fragment
118
+ // depending on the response_mode (query or fragment)
119
+ let issParam = redirectUrl.searchParams.get('iss')
120
+ if (!issParam && redirectUrl.hash) {
121
+ // Check in the hash fragment
122
+ const hashParams = new URLSearchParams(redirectUrl.hash.substring(1))
123
+ issParam = hashParams.get('iss')
124
+ }
125
+
126
+ console.log('Redirect URL:', mockRes.redirectUrl)
127
+ console.log('RFC 9207 - iss parameter in redirect:', issParam)
128
+
129
+ // RFC 9207: The iss parameter MUST be present and match the provider issuer
130
+ expect(issParam, 'RFC 9207: iss parameter must be present in authorization response').to.exist
131
+ expect(issParam).to.not.be.null
132
+ expect(issParam).to.equal(providerUri)
133
+ })
41
134
  })
42
- })
135
+ })
@@ -93,7 +93,8 @@ describe('PATCH through text/n3', () => {
93
93
  }, { // expected:
94
94
  status: 201,
95
95
  text: 'Patch applied successfully',
96
- result: '@prefix : </new.ttl#>.\n@prefix tim: </>.\n\ntim:x tim:y tim:z.\n\n'
96
+ // result: '@prefix : </new.ttl#>.\n@prefix tim: </>.\n\ntim:x tim:y tim:z.\n\n'
97
+ result: '@prefix : </new.ttl#>.\n\n</x> </y> </z>.\n\n'
97
98
  }))
98
99
 
99
100
  describe('on a non-existent JSON-LD file', describePatch({
@@ -105,7 +106,7 @@ describe('PATCH through text/n3', () => {
105
106
  status: 201,
106
107
  text: 'Patch applied successfully',
107
108
  // result: '{\n "@id": "/x",\n "/y": {\n "@id": "/z"\n }\n}'
108
- result: `{
109
+ /* result: `{
109
110
  "@context": {
110
111
  "tim": "https://tim.localhost:7777/"
111
112
  },
@@ -113,6 +114,12 @@ describe('PATCH through text/n3', () => {
113
114
  "tim:y": {
114
115
  "@id": "tim:z"
115
116
  }
117
+ }` */
118
+ result: `{
119
+ "@id": "https://tim.localhost:7777/x",
120
+ "https://tim.localhost:7777/y": {
121
+ "@id": "https://tim.localhost:7777/z"
122
+ }
116
123
  }`
117
124
  }))
118
125
 
@@ -140,7 +147,8 @@ describe('PATCH through text/n3', () => {
140
147
  }, { // expected:
141
148
  status: 201,
142
149
  text: 'Patch applied successfully',
143
- result: '@prefix : </new.n3#>.\n@prefix tim: </>.\n\ntim:x tim:y tim:z.\n\n'
150
+ // result: '@prefix : </new.n3#>.\n@prefix tim: </>.\n\ntim:x tim:y tim:z.\n\n'
151
+ result: '@prefix : </new.n3#>.\n\n</x> </y> </z>.\n\n'
144
152
  }))
145
153
 
146
154
  describe('on an N3 file that has an invalid uri (*.acl)', describePatch({
@@ -179,7 +187,8 @@ describe('PATCH through text/n3', () => {
179
187
  }, { // expected:
180
188
  status: 200,
181
189
  text: 'Patch applied successfully',
182
- result: '@prefix : </append-only.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:b tim:c.\n\ntim:d tim:e tim:f.\n\ntim:x tim:y tim:z.\n\n'
190
+ // result: '@prefix : </append-only.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:b tim:c.\n\ntim:d tim:e tim:f.\n\ntim:x tim:y tim:z.\n\n'
191
+ result: '@prefix : </append-only.ttl#>.\n\n</a> </b> </c>.\n\n</d> </e> </f>.\n\n</x> </y> </z>.\n\n'
183
192
  }))
184
193
 
185
194
  describe('on a resource with write-only access', describePatch({
@@ -189,7 +198,8 @@ describe('PATCH through text/n3', () => {
189
198
  }, { // expected:
190
199
  status: 200,
191
200
  text: 'Patch applied successfully',
192
- result: '@prefix : </write-only.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:b tim:c.\n\ntim:d tim:e tim:f.\n\ntim:x tim:y tim:z.\n\n'
201
+ // result: '@prefix : </write-only.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:b tim:c.\n\ntim:d tim:e tim:f.\n\ntim:x tim:y tim:z.\n\n'
202
+ result: '@prefix : </write-only.ttl#>.\n\n</a> </b> </c>.\n\n</d> </e> </f>.\n\n</x> </y> </z>.\n\n'
193
203
  }))
194
204
 
195
205
  describe('on a resource with parent folders that do not exist', describePatch({
@@ -200,7 +210,8 @@ describe('PATCH through text/n3', () => {
200
210
  }, {
201
211
  status: 201,
202
212
  text: 'Patch applied successfully',
203
- result: '@prefix : <#>.\n@prefix fol: <./>.\n\nfol:x fol:y fol:z.\n\n'
213
+ // result: '@prefix : <#>.\n@prefix fol: <./>.\n\nfol:x fol:y fol:z.\n\n'
214
+ result: '@prefix : <#>.\n\n<x> <y> <z>.\n\n'
204
215
  }))
205
216
  })
206
217
 
@@ -258,7 +269,8 @@ describe('PATCH through text/n3', () => {
258
269
  }, { // expected:
259
270
  status: 200,
260
271
  text: 'Patch applied successfully',
261
- result: '@prefix : </read-append.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:b tim:c; tim:y tim:z.\n\ntim:d tim:e tim:f.\n\n'
272
+ // result: '@prefix : </read-append.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:b tim:c; tim:y tim:z.\n\ntim:d tim:e tim:f.\n\n'
273
+ result: '@prefix : </read-append.ttl#>.\n\n</a> </b> </c>; </y> </z>.\n\n</d> </e> </f>.\n\n'
262
274
  }))
263
275
 
264
276
  describe('with a non-matching WHERE clause', describePatch({
@@ -281,7 +293,8 @@ describe('PATCH through text/n3', () => {
281
293
  }, { // expected:
282
294
  status: 200,
283
295
  text: 'Patch applied successfully',
284
- result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:b tim:c; tim:y tim:z.\n\ntim:d tim:e tim:f.\n\n'
296
+ // result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:b tim:c; tim:y tim:z.\n\ntim:d tim:e tim:f.\n\n'
297
+ result: '@prefix : </read-write.ttl#>.\n\n</a> </b> </c>; </y> </z>.\n\n</d> </e> </f>.\n\n'
285
298
  }))
286
299
 
287
300
  describe('with a non-matching WHERE clause', describePatch({
@@ -354,7 +367,8 @@ describe('PATCH through text/n3', () => {
354
367
  }, { // expected:
355
368
  status: 200,
356
369
  text: 'Patch applied successfully',
357
- result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:d tim:e tim:f.\n\n'
370
+ // result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:d tim:e tim:f.\n\n'
371
+ result: '@prefix : </read-write.ttl#>.\n\n</d> </e> </f>.\n\n'
358
372
  }))
359
373
 
360
374
  describe('with a patch for non-existing data', describePatch({
@@ -374,7 +388,8 @@ describe('PATCH through text/n3', () => {
374
388
  }, { // expected:
375
389
  status: 200,
376
390
  text: 'Patch applied successfully',
377
- result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:d tim:e tim:f.\n\n'
391
+ // result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:d tim:e tim:f.\n\n'
392
+ result: '@prefix : </read-write.ttl#>.\n\n</d> </e> </f>.\n\n'
378
393
  }))
379
394
 
380
395
  describe('with a non-matching WHERE clause', describePatch({
@@ -463,7 +478,8 @@ describe('PATCH through text/n3', () => {
463
478
  }, { // expected:
464
479
  status: 200,
465
480
  text: 'Patch applied successfully',
466
- result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:d tim:e tim:f.\n\ntim:x tim:y tim:z.\n\n'
481
+ // result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:d tim:e tim:f.\n\ntim:x tim:y tim:z.\n\n'
482
+ result: '@prefix : </read-write.ttl#>.\n\n</d> </e> </f>.\n\n</x> </y> </z>.\n\n'
467
483
  }))
468
484
 
469
485
  describe('with a patch for non-existing data', describePatch({
@@ -485,7 +501,8 @@ describe('PATCH through text/n3', () => {
485
501
  }, { // expected:
486
502
  status: 200,
487
503
  text: 'Patch applied successfully',
488
- result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:y tim:z.\n\ntim:d tim:e tim:f.\n\n'
504
+ // result: '@prefix : </read-write.ttl#>.\n@prefix tim: </>.\n\ntim:a tim:y tim:z.\n\ntim:d tim:e tim:f.\n\n'
505
+ result: '@prefix : </read-write.ttl#>.\n\n</a> </y> </z>.\n\n</d> </e> </f>.\n\n'
489
506
  }))
490
507
 
491
508
  describe('with a non-matching WHERE clause', describePatch({
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-unused-expressions */
2
1
  import path from 'path'
3
2
  import chai from 'chai'
4
3
 
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-unused-expressions */
2
1
  import supertest from 'supertest'
3
2
  import rdf from 'rdflib'
4
3
  import ldnode from '../../index.mjs'
@@ -1 +1 @@
1
- {"redirect_uris":["https://localhost:3457/api/oidc/rp/https%3A%2F%2Flocalhost%3A3457"],"client_id":"30860bb5cf6ba07e80ed7b2e7178c7ad","client_secret":"1c1e6e8931bbc9b4eee4cd8ae84fe8e5","response_types":["code","id_token token","code id_token token"],"grant_types":["authorization_code","implicit","refresh_token","client_credentials"],"application_type":"web","client_name":"Solid OIDC RP for https://localhost:3457","id_token_signed_response_alg":"RS256","token_endpoint_auth_method":"client_secret_basic","default_max_age":86400,"post_logout_redirect_uris":["https://localhost:3457/goodbye"]}
1
+ {"redirect_uris":["https://localhost:3457/api/oidc/rp/https%3A%2F%2Flocalhost%3A3457"],"client_id":"e989e9f58cf29869c56a68ceb4256b69","client_secret":"83b4b30768f1e17b70b54812242c757c","response_types":["code","id_token token","code id_token token"],"grant_types":["authorization_code","implicit","refresh_token","client_credentials"],"application_type":"web","client_name":"Solid OIDC RP for https://localhost:3457","id_token_signed_response_alg":"RS256","token_endpoint_auth_method":"client_secret_basic","default_max_age":86400,"post_logout_redirect_uris":["https://localhost:3457/goodbye"]}