11/* eslint-disable max-len */
22
33import { fetch } from 'cross-fetch' ;
4- import { Parser , Store } from 'n3' ;
4+ import { Parser , Writer , Store } from 'n3' ;
5+ import { demoPolicy } from "./policyCreation" ;
6+
7+ const parser = new Parser ( ) ;
8+ const writer = new Writer ( ) ;
59
610const terms = {
711 solid : {
@@ -14,64 +18,31 @@ const terms = {
1418 filters : {
1519 bday : 'http://localhost:3000/catalog/public/filters/bday' ,
1620 age : 'http://localhost:3000/catalog/public/filters/age' ,
21+ } ,
22+ views : {
23+ bday : 'http://localhost:3000/ruben/private/derived/bday' ,
24+ age : 'http://localhost:3000/ruben/private/derived/age' ,
25+ } ,
26+ agents : {
27+ ruben : 'http://localhost:3000/ruben/profile/card#me' ,
28+ vendor : 'http://localhost:3000/demo/public/vendor' ,
29+ present : 'http://localhost:3000/demo/public/bday-app' ,
30+ } ,
31+ scopes : {
32+ read : 'urn:example:css:modes:read' ,
1733 }
1834}
1935
20- const parser = new Parser ( ) ;
21-
22- const privateRequest = async ( resource_id : string , tokenEndpoint : string ) => {
23- const claim_token = "http://localhost:3000/demo/public/bday-app"
24-
25- const content = {
26- grant_type : 'urn:ietf:params:oauth:grant-type:uma-ticket' ,
27- claim_token : encodeURIComponent ( claim_token ) ,
28- claim_token_format : 'urn:solidlab:uma:claims:formats:webid' ,
29- // ticket,
30- permissions : [ {
31- resource_id,
32- resource_scopes : [ 'urn:example:css:modes:read' , 'urn:example:css:modes:write' ] ,
33- } ]
34- } ;
35-
36- const asRequestResponse = await fetch ( tokenEndpoint , {
37- method : "POST" ,
38- headers : {
39- "content-type" :"application/json"
40- } ,
41- body : JSON . stringify ( content ) ,
42- } ) ;
43-
44- const asResponse = await asRequestResponse . json ( ) ;
45- const tokenResponse = await fetch ( resource_id , {
46- headers : { 'Authorization' : `${ asResponse . token_type } ${ asResponse . access_token } ` }
47- } ) ;
48- }
49-
50- const log = ( msg : string , obj ?: any ) => {
51- console . log ( '' ) ;
52- console . log ( msg ) ;
53- if ( obj ) {
54- console . log ( '\n' ) ;
55- console . log ( obj ) ;
56- }
57- }
58-
59- function parseJwt ( token :string ) {
60- return JSON . parse ( Buffer . from ( token . split ( '.' ) [ 1 ] , 'base64' ) . toString ( ) ) ;
61- }
62-
6336async function main ( ) {
6437
6538 log ( `Alright, so, for the demo ...` ) ;
6639
67- const webId = 'http://localhost:3000/ruben/profile/card#me' ;
68-
69- log ( `Ruben V., a.k.a. <${ webId } >, has some private data in <http://localhost:3000/ruben/private/data>.` ) ;
40+ log ( `Ruben V., a.k.a. <${ terms . agents . ruben } >, has some private data in <http://localhost:3000/ruben/private/data>.` ) ;
7041
7142 log ( `Of course, he does not want everyone to be able to see all of his private data when they need just one aspect of it. Therefore, Ruben has installed two Views on his data, based on SPARQL filters from a public Catalog. (When and how this is done is out-of-scope for now.)` ) ;
7243
73- const webIdData = new Store ( parser . parse ( await ( await fetch ( webId ) ) . text ( ) ) ) ;
74- const viewIndex = webIdData . getObjects ( webId , terms . solid . viewIndex , null ) [ 0 ] . value ;
44+ const webIdData = new Store ( parser . parse ( await ( await fetch ( terms . agents . ruben ) ) . text ( ) ) ) ;
45+ const viewIndex = webIdData . getObjects ( terms . agents . ruben , terms . solid . viewIndex , null ) [ 0 ] . value ;
7546 const views = Object . fromEntries ( webIdData . getObjects ( viewIndex , terms . solid . entry , null ) . map ( entry => {
7647 const filter = webIdData . getObjects ( entry , terms . solid . filter , null ) [ 0 ] . value ;
7748 const location = webIdData . getObjects ( entry , terms . solid . location , null ) [ 0 ] . value ;
@@ -83,11 +54,11 @@ async function main() {
8354 log ( `(1) <${ views [ terms . filters . bday ] } > filters out his birth date, according to the <${ terms . filters . bday } > filter` ) ;
8455 log ( `(2) <${ views [ terms . filters . age ] } > derives his age, according to the <${ terms . filters . bday } > filter` ) ;
8556
86- const policyDir = 'http://localhost:3000/ruben/settings/policies/' ;
57+ const policyContainer = 'http://localhost:3000/ruben/settings/policies/' ;
8758
88- log ( `Access to Ruben's data is based on policies he manages through his Authz Companion app, and which are stored in <${ policyDir } >. (This is, of course, not publicly known.)` ) ;
59+ log ( `Access to Ruben's data is based on policies he manages through his Authz Companion app, and which are stored in <${ policyContainer } >. (This is, of course, not publicly known.)` ) ;
8960
90- const umaServer = webIdData . getObjects ( webId , terms . solid . umaServer , null ) [ 0 ] . value ;
61+ const umaServer = webIdData . getObjects ( terms . agents . ruben , terms . solid . umaServer , null ) [ 0 ] . value ;
9162 const configUrl = new URL ( '.well-known/uma2-configuration' , umaServer ) ;
9263 const umaConfig = await ( await fetch ( configUrl ) ) . json ( ) ;
9364 const tokenEndpoint = umaConfig . token_endpoint ;
@@ -101,17 +72,29 @@ async function main() {
10172
10273 log ( `Having been notified in some way of the access request, Ruben could go to his Authz Companion app, and add a policy allowing the requested access.` ) ;
10374
104- const privateResource = "http://localhost:3000/ruben/private/derived/age"
105- const claim_token = "http://localhost:3000/demo/public/bday-app"
75+ const startDate = new Date ( ) ;
76+ const endDate = new Date ( startDate . valueOf ( ) + 14 * 24 * 60 * 60 * 1000 ) ;
77+ const purpose = 'age-verification'
78+ const policy = demoPolicy ( terms . views . age , terms . agents . vendor , { startDate, endDate, purpose } )
79+
80+ const policyCreationResponse = await fetch ( policyContainer , {
81+ method : 'POST' ,
82+ headers : { 'content-type' : 'text/turtle' } ,
83+ body : writer . quadsToString ( policy . representation . getQuads ( null , null , null , null ) )
84+ } ) ;
85+
86+ if ( policyCreationResponse . status !== 201 ) { log ( 'Adding a policy did not succeed...' ) ; throw 0 ; }
87+
88+ log ( `Now that the policy has been set, and the agent has possibly been notified in some way, the agent can try the access request again.` ) ;
10689
10790 const content = {
108- grant_type : 'urn:ietf:params:oauth:grant-type:uma-ticket' ,
109- claim_token : encodeURIComponent ( claim_token ) ,
91+ // grant_type: 'urn:ietf:params:oauth:grant-type:uma-ticket',
92+ claim_token : encodeURIComponent ( terms . agents . vendor ) ,
11093 claim_token_format : 'urn:solidlab:uma:claims:formats:webid' ,
11194 // ticket,
11295 permissions : [ {
113- resource_id : privateResource ,
114- resource_scopes : [ 'urn:example:css:modes: read' ] ,
96+ resource_id : terms . views . age ,
97+ resource_scopes : [ terms . scopes . read ] ,
11598 } ]
11699 } ;
117100
@@ -121,9 +104,7 @@ async function main() {
121104
122105 const asRequestResponse = await fetch ( tokenEndpoint , {
123106 method : "POST" ,
124- headers : {
125- "content-type" :"application/json"
126- } ,
107+ headers : { "content-type" :"application/json" } ,
127108 body : JSON . stringify ( content ) ,
128109 } )
129110
@@ -140,13 +121,13 @@ async function main() {
140121 console . log ( { ...asResponse , access_token : asResponse . access_token . slice ( 0 , 10 ) . concat ( '...' ) } ) ;
141122 console . log ( '\n' ) ;
142123
143- // for (const permission of decodedToken.permissions) {
144- // console.log(`Permissioned scopes for resource ${permission.resource_id}:`, permission.resource_scopes)
145- // }
124+ for ( const permission of decodedToken . permissions ) {
125+ console . log ( `Permissioned scopes for resource ${ permission . resource_id } :` , permission . resource_scopes )
126+ }
146127
147- console . log ( `=== Trying to create private resource <${ privateResource } > WITH access token.\n` ) ;
128+ console . log ( `=== Trying to create private resource <${ terms . views . age } > WITH access token.\n` ) ;
148129
149- const tokenResponse = await fetch ( privateResource , {
130+ const tokenResponse = await fetch ( terms . views . age , {
150131 headers : { 'Authorization' : `${ asResponse . token_type } ${ asResponse . access_token } ` }
151132 } ) ;
152133
@@ -157,3 +138,19 @@ async function main() {
157138}
158139
159140main ( ) ;
141+
142+
143+ /* Helper functions */
144+
145+ function parseJwt ( token :string ) {
146+ return JSON . parse ( Buffer . from ( token . split ( '.' ) [ 1 ] , 'base64' ) . toString ( ) ) ;
147+ }
148+
149+ function log ( msg : string , obj ?: any ) {
150+ console . log ( '' ) ;
151+ console . log ( msg ) ;
152+ if ( obj ) {
153+ console . log ( '\n' ) ;
154+ console . log ( obj ) ;
155+ }
156+ }
0 commit comments