From 5d2eb8c23dc92c547d61d28ec4f3d618e5326300 Mon Sep 17 00:00:00 2001 From: Sergey Malinin Date: Tue, 4 Sep 2018 19:57:13 +1000 Subject: [PATCH 1/6] Fix for support multi oidcIssuer relations per profile --- src/oidc-manager.js | 2 +- src/preferred-provider.js | 68 ++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/oidc-manager.js b/src/oidc-manager.js index 393176c..a4ce0f7 100644 --- a/src/oidc-manager.js +++ b/src/oidc-manager.js @@ -379,7 +379,7 @@ class OidcManager { } // Otherwise, verify that issuer is the preferred OIDC provider for the web id - return discoverProviderFor(webId) + return discoverProviderFor(webId, issuer) .then(preferredProvider => { if (preferredProvider === issuer) { // everything checks out return webId diff --git a/src/preferred-provider.js b/src/preferred-provider.js index b29ae02..ec1a877 100644 --- a/src/preferred-provider.js +++ b/src/preferred-provider.js @@ -61,20 +61,50 @@ function providerExists (uri) { * given Web ID, extracted from Link rel header or profile body. If no * provider URI was found, reject with an error. */ -function discoverProviderFor (webId) { +function discoverProviderFor (webId, issuer) { return discoverFromHeaders(webId) - .then(providerFromHeaders => providerFromHeaders || discoverFromProfile(webId)) + .then(providerFromHeaders => providerFromHeaders || discoverAllFromProfile(webId)) .then(providerUri => { - // drop the path (provider origin only) - if (providerUri) { - providerUri = (new URL(providerUri)).origin + if (Array.isArray(providerUri)) { + let list = providerUri + let lastErr = null + + for (let i = 0; i < list.length; i++) { + lastErr = null + providerUri = list[i]; + if (providerUri) { + providerUri = (new URL(providerUri)).origin + } + + try { + validateProviderUri(providerUri, webId) // Throw an error if empty or invalid + } catch (err) { + lastErr = err + } + + if (lastErr == null && issuer && providerUri == issuer) { + return providerUri + } + } + if (lastErr) { + throw lastErr + } else { + validateProviderUri(null, webId) // Throw an error if empty or invalid + } + + } else { + + // drop the path (provider origin only) + if (providerUri) { + providerUri = (new URL(providerUri)).origin + } + + validateProviderUri(providerUri, webId) // Throw an error if empty or invalid + + return providerUri } - - validateProviderUri(providerUri, webId) // Throw an error if empty or invalid - - return providerUri }) } @@ -94,16 +124,30 @@ function discoverFromHeaders (webId) { }) } -function discoverFromProfile (webId) { +function discoverAllFromProfile (webId) { const store = rdf.graph() const fetcher = rdf.fetcher(store) return fetcher.load(webId, { force: true }) .then(response => { + if (!response.ok) { + let error = new Error(`Could not reach Web ID ${webId} to discover provider`) + error.statusCode = 400 + throw error + } + let providerTerm = rdf.namedNode('http://www.w3.org/ns/solid/terms#oidcIssuer') - let providerUri = store.anyValue(rdf.namedNode(webId), providerTerm) - return providerUri + let idp = store.each(rdf.namedNode(webId), providerTerm, undefined) + let list = []; + + for(let i = 0; i < idp.length; i++) { + if (idp[i].uri) { + list.push(idp[i].uri) + } + } + + return list }, err => { let error = new Error(`Could not reach Web ID ${webId} to discover provider`) error.cause = err From 945d9f4b5919841d80089ec0e09bef237b53fd9b Mon Sep 17 00:00:00 2001 From: Sergey Malinin Date: Tue, 11 Sep 2018 22:10:33 +1000 Subject: [PATCH 2/6] Fix JS format issues --- src/preferred-provider.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/preferred-provider.js b/src/preferred-provider.js index ec1a877..de475ba 100644 --- a/src/preferred-provider.js +++ b/src/preferred-provider.js @@ -73,29 +73,27 @@ function discoverProviderFor (webId, issuer) { for (let i = 0; i < list.length; i++) { lastErr = null - providerUri = list[i]; + providerUri = list[i] if (providerUri) { providerUri = (new URL(providerUri)).origin } - + try { validateProviderUri(providerUri, webId) // Throw an error if empty or invalid } catch (err) { lastErr = err } - if (lastErr == null && issuer && providerUri == issuer) { + if (lastErr === null && issuer && providerUri === issuer) { return providerUri } } if (lastErr) { - throw lastErr + throw lastErr } else { validateProviderUri(null, webId) // Throw an error if empty or invalid } - - } else { - + } else { // drop the path (provider origin only) if (providerUri) { providerUri = (new URL(providerUri)).origin @@ -139,9 +137,9 @@ function discoverAllFromProfile (webId) { let providerTerm = rdf.namedNode('http://www.w3.org/ns/solid/terms#oidcIssuer') let idp = store.each(rdf.namedNode(webId), providerTerm, undefined) - let list = []; + let list = [] - for(let i = 0; i < idp.length; i++) { + for (let i = 0; i < idp.length; i++) { if (idp[i].uri) { list.push(idp[i].uri) } From 003926f0bb7733d925f5de41dc05a0531bc20195 Mon Sep 17 00:00:00 2001 From: Sergey Malinin Date: Tue, 11 Sep 2018 23:49:07 +1000 Subject: [PATCH 3/6] Fix issue with test for preferred-provider.js --- src/preferred-provider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preferred-provider.js b/src/preferred-provider.js index de475ba..394fc03 100644 --- a/src/preferred-provider.js +++ b/src/preferred-provider.js @@ -84,7 +84,7 @@ function discoverProviderFor (webId, issuer) { lastErr = err } - if (lastErr === null && issuer && providerUri === issuer) { + if (lastErr === null && (issuer && providerUri === issuer) || !issuer) { return providerUri } } From bd61dbc2fd44ae91c9498b4602f0b37ebd0f4f72 Mon Sep 17 00:00:00 2001 From: Sergey Malinin Date: Tue, 11 Sep 2018 23:50:40 +1000 Subject: [PATCH 4/6] Add test for check support of multi oidcIssuer --- test/unit/preferred-provider-test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/unit/preferred-provider-test.js b/test/unit/preferred-provider-test.js index 7963fb8..72d99d7 100644 --- a/test/unit/preferred-provider-test.js +++ b/test/unit/preferred-provider-test.js @@ -64,6 +64,23 @@ describe('preferred-provider.js', () => { }) }) + it('should extract and validate the provider uri from the webid profile with multi oidcIssuer', () => { + nock(serverUri) + .options('/') + .reply(204, 'No content') + + nock(serverUri) + .get('/') + .reply(200, sampleProfileSrc, { + 'Content-Type': 'text/turtle' + }) + + return provider.discoverProviderFor(webId, 'https://provider.com') + .then(providerUri => { + expect(providerUri).to.equal('https://provider.com') + }) + }) + it('should throw an error if webid is reachable but no provider uri found', done => { nock(serverUri) .options('/') From 1d75adef7bea9f17f26014f7560507641d2a0126 Mon Sep 17 00:00:00 2001 From: Sergey Malinin Date: Tue, 11 Sep 2018 23:51:16 +1000 Subject: [PATCH 5/6] Add resource for test --- test/resources/sample-webid-profile1.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 test/resources/sample-webid-profile1.js diff --git a/test/resources/sample-webid-profile1.js b/test/resources/sample-webid-profile1.js new file mode 100644 index 0000000..e4529e6 --- /dev/null +++ b/test/resources/sample-webid-profile1.js @@ -0,0 +1,20 @@ +module.exports = ` +@prefix solid: . +@prefix foaf: . +@prefix pim: . +@prefix schema: . +@prefix ldp: . + +<> + a foaf:PersonalProfileDocument ; + foaf:primaryTopic <#me> . + +<#me> + a schema:Person ; + + solid:account ; # link to the account uri + pim:storage ; # root storage + + solid:oidcIssuer ; + solid:oidcIssuer . +` From 4a4d3991ab477ad0f9d658c37abbf59afed3ad44 Mon Sep 17 00:00:00 2001 From: Sergey Malinin Date: Tue, 11 Sep 2018 23:57:43 +1000 Subject: [PATCH 6/6] Fix missprint in discoverProviderFor() --- src/preferred-provider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preferred-provider.js b/src/preferred-provider.js index 394fc03..169855c 100644 --- a/src/preferred-provider.js +++ b/src/preferred-provider.js @@ -84,7 +84,7 @@ function discoverProviderFor (webId, issuer) { lastErr = err } - if (lastErr === null && (issuer && providerUri === issuer) || !issuer) { + if (lastErr === null && ((issuer && providerUri === issuer) || !issuer)) { return providerUri } }