Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@
- The browser-reported `Origin` header will now be checked by
default, and the ACL system can be used to restrict access
to applications for added security.
- Users can add `trustedApp` entries to their profile using a new databrowser pane.
You will see an 'A' icon added while you view a Person's profile URL
with the data browser (might have to hit refresh in your browser and make sure you
are viewing a WebId URL like https://localhost:8443/profile/card#me).
- Logging is now verbose by default so the `-v` option has been
removed and a `--quiet` option has been added to mute the log.
- To be bug compliant with 4.x releases, if a rule for public readable
root / does not exist, it will check in /index.html.acl (see issue #1063)
- Command line options are now kebab-cased rather than camelCased,
config options may be both.
- Resource with no extension now have '$.ttl' appended in the filename (see upgrades notes below).
- Many smaller fixes.

#### 5.0.0 Upgrade Notes
Expand Down
12 changes: 10 additions & 2 deletions lib/acl-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,16 @@ class ACLChecker {
const modes = [ACL(mode)]
const agentOrigin = this.agentOrigin
const trustedOrigins = this.trustedOrigins
const accessDenied = aclCheck.accessDenied(acl.graph, resource, directory, aclFile, agent, modes, agentOrigin, trustedOrigins)

let originTrustedModes = []
try {
this.fetch(aclFile.doc().value)
originTrustedModes = await aclCheck.getTrustedModesForOrigin(acl.graph, resource, directory, aclFile, agentOrigin, (uriNode) => {
return this.fetch(uriNode.doc().value, acl.graph)
})
} catch (e) {
console.error(e.message)
}
const accessDenied = aclCheck.accessDenied(acl.graph, resource, directory, aclFile, agent, modes, agentOrigin, trustedOrigins, originTrustedModes)
if (accessDenied && user) {
this.messagesCached[cacheKey].push(HTTPError(403, accessDenied))
} else if (accessDenied) {
Expand Down
52 changes: 48 additions & 4 deletions test/integration/authentication-oidc-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ const path = require('path')
const fs = require('fs-extra')
const { UserStore } = require('@solid/oidc-auth-manager')
const UserAccount = require('../../lib/models/user-account')
const SolidAuthOIDC = require('@solid/solid-auth-oidc')
// const SolidAuthOIDC = require('@solid/solid-auth-oidc')

const fetch = require('node-fetch')
const localStorage = require('localstorage-memory')
// const fetch = require('node-fetch')
// const localStorage = require('localstorage-memory')
const URL = require('whatwg-url').URL
global.URL = URL
global.URLSearchParams = require('whatwg-url').URLSearchParams
Expand All @@ -20,7 +20,7 @@ chai.use(require('dirty-chai'))
// In this test we always assume that we are Alice

describe('Authentication API (OIDC)', () => {
let alice, bob
let alice, bob // eslint-disable-line no-unused-vars

let aliceServerUri = 'https://localhost:7000'
let aliceWebId = 'https://localhost:7000/profile/card#me'
Expand All @@ -35,6 +35,8 @@ describe('Authentication API (OIDC)', () => {
let bobDbPath = path.join(__dirname,
'../resources/accounts-scenario/bob/db')

const trustedAppUri = 'https://trusted.app'

const serverConfig = {
sslKey: path.join(__dirname, '../keys/key.pem'),
sslCert: path.join(__dirname, '../keys/cert.pem'),
Expand Down Expand Up @@ -437,6 +439,48 @@ describe('Authentication API (OIDC)', () => {
expect(response).to.have.property('status', 401)
})
})

describe('with trusted app and no cookie', () => {
before(done => {
alice.get('/private-for-alice.txt')
.set('Origin', trustedAppUri)
.end((err, res) => {
response = res
done(err)
})
})

it('should return a 401', () => expect(response).to.have.property('status', 401))
})

describe('with trusted app and malicious cookie', () => {
before(done => {
var malcookie = cookie.replace(/connect\.sid=(\S+)/, 'connect.sid=l33th4x0rzp0wn4g3;')
alice.get('/private-for-alice.txt')
.set('Cookie', malcookie)
.set('Origin', trustedAppUri)
.end((err, res) => {
response = res
done(err)
})
})

it('should return a 401', () => expect(response).to.have.property('status', 401))
})

describe('with trusted app and correct cookie', () => {
before(done => {
alice.get('/private-for-alice.txt')
.set('Cookie', cookie)
.set('Origin', trustedAppUri)
.end((err, res) => {
response = res
done(err)
})
})

it('should return a 200', () => expect(response).to.have.property('status', 200))
})
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ describe('Authentication API (OIDC) - With strict origins turned off', () => {
const bobServerUri = `https://localhost:${bobServerPort}`
let bobDbPath = path.join(__dirname, '../resources/accounts-strict-origin-off/bob/db')

const trustedAppUri = 'https://trusted.app'

const serverConfig = {
sslKey: path.join(__dirname, '../keys/key.pem'),
sslCert: path.join(__dirname, '../keys/cert.pem'),
Expand Down Expand Up @@ -194,6 +196,18 @@ describe('Authentication API (OIDC) - With strict origins turned off', () => {
})
})

it('should return a 401', () => expect(response).to.have.property('status', 401))
})
describe('and trusted app', () => {
before(done => {
alice.get('/private-for-alice.txt')
.set('Origin', trustedAppUri)
.end((err, res) => {
response = res
done(err)
})
})

it('should return a 401', () => expect(response).to.have.property('status', 401))
})
})
Expand Down Expand Up @@ -251,6 +265,21 @@ describe('Authentication API (OIDC) - With strict origins turned off', () => {
// Even if origin checking is disabled, then this should return a 401 because cookies should not be trusted cross-origin
it('should return a 401', () => expect(response).to.have.property('status', 401))
})

describe('and trusted app', () => {
// Trusted apps are not supported when strictOrigin check is turned off
before(done => {
alice.get('/private-for-alice.txt')
.set('Cookie', cookie)
.set('Origin', trustedAppUri)
.end((err, res) => {
response = res
done(err)
})
})

it('should return a 401', () => expect(response).to.have.property('status', 401))
})
})

describe('with malicious cookie', () => {
Expand Down Expand Up @@ -310,6 +339,20 @@ describe('Authentication API (OIDC) - With strict origins turned off', () => {

it('should return a 401', () => expect(response).to.have.property('status', 401))
})

describe('and trusted app', () => {
before(done => {
alice.get('/private-for-alice.txt')
.set('Cookie', malcookie)
.set('Origin', trustedAppUri)
.end((err, res) => {
response = res
done(err)
})
})

it('should return a 401', () => expect(response).to.have.property('status', 401))
})
})
})
})
Expand Down
4 changes: 4 additions & 0 deletions test/resources/accounts-scenario/alice/profile/card$.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@prefix acl: <http://www.w3.org/ns/auth/acl#>.

<#me> acl:trustedApp [ acl:origin <https://trusted.app>;
acl:mode acl:Read, acl:Write, acl:Append, acl:Control].
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@prefix acl: <http://www.w3.org/ns/auth/acl#>.

<#me> acl:trustedApp [ acl:origin <https://trusted.app>;
acl:mode acl:Read, acl:Write, acl:Append, acl:Control].