This document tries to summarize the use of the credentials in the BCN pilots, covering all cases (log-in to dashboard, credential use) except the specific details of the petition signature process. It is aimed as a guide for further pilots, to unify vocabulary and simplify interaction among developers.
- Variables are referenced like
$variable - Important ontology elements are referenced with CAPS (like
CREDENTIAL ISSUER). - We try to use the same terminology as possible for both pilots, named DDDC and IoT respectively.
- PLEASE try to document the repsective APIs using OpenAPI specs or something similar (swagger).
- BCN Pilot partners:
- Infrastructure:
- Zencode scripts for the COCONUT flow are available here: https://github.com/DECODEproject/dddc-pilot-contracts (as development evolves really quickly, if you use contracts, do NOT copy them, but link them using
git submoduletrick). - Zencode contracts with example on coconut credentials: https://github.com/DECODEproject/zenroom/tree/master/examples/zencode_coconut
- Credential issuer service API developed by Dyne - https://github.com/DECODEproject/dddc-credential-issuer
- IoT components developped by Thingful and hosted by Smart Citizen.
- Zencode scripts for the COCONUT flow are available here: https://github.com/DECODEproject/dddc-pilot-contracts (as development evolves really quickly, if you use contracts, do NOT copy them, but link them using
Please SAM add relevant links to repos
- BCN
dashboard, repo and link - DECODE Phone-App, repo and Google Play and Apple Store (not yet public).
Please JORDI can we rename the repo into decodeproject/app ?
- DECODE specific IoT-Web-App
- IoT components (policy store, encrypted datastore) developed by Thingful (TH and hosted by Smart Citizen (SC)
Please SAM add relevant link to repo and explain stack
- @All: Read doc
- @Sam & @Rohit: Modify flow and add extra steps
- BCNNow Dashboard @Rohit:
- Create API with three exposed methods: Log-in, create_dashbord_encrypted (IoT pilot) and create_dashboard_unencrypted (DDDC)
- Agree signature API calls with @Sam and @Jordi
- Document API and write example calls for DDDC admin and Policy Store admin respectively
- Phone-App @Jordi:
- Implement UX for data sharing with Dashboard
- Implement calls for log-in and Credential issuer obtention
- Implement calls for credential issuer interaction
- Web-App @Sam:
- Agree with @Jordi and document policy store API calls
- Implement log-in calls to dashboard
- Implement calls for Credential issuer obtention
- DDDC website @Anders:
- Implement calls for dashboard set-up
- Implement calls for credential issuer api set-up
- POlicy store @Sam:
- Implement logic to set up credential issuer and dashboard once SC admin triggers it and coordinate integration with @Guillem.
- SC website @Guillem:
- Coordinate with Sam to make everythin run
- Credential issuer API @Puria:
- Implement changes to API credential to break 1 to one mapping
- DDDC
- Dashboard API to work by 7th March
- March 7th, all DDDC working except log-in flow
- March 21st, all in production and app with log-in flow implemented
- April 1st, all working smoothly
- Credential ISSUER API changes effective by March 5th
- Petitions connector API ready by March 11th
- IoT
- Web-app to work with entire flow by 24th March
- Dashboard API to work by 7th March
- Credential ISSUER API changes effective by March 7th
- IoT Phone-app to work by April 1st
- All production working by April 15th.
- Admin (DDDC or Smart Citizen) which is in charge of setting up both
BCNNOWand theCREDENTIAL ISSUER API SERVICEfollowing the rules accorded with the respective users in off-line sessions. This admin needs a$bcnnow-api-tokenand a$ci-api-tokento communicate securely with the respective APIs. Additionaly, for the case of the IoT, SC admin also needs to be able to communicate securely with thePOLICY STORE. - The admin, in particular, needs to define the
ATTRIBUTEwhich will require to be verified in order to participate in the pilots. ThoseATTRIBUTESwill have the following properties:$autorizable_attribute_id: Unique ID identiying theATTRIBUTE(attribute susceptible to be validated via a credential)$autorizable_attribute_info: Group of($attribute_info_key:($attibute_info_type, $attribute_info_value)that the users will need to provide in order to obtain a credential. The contents of the$attribute_info(key,value) pairs provided by the user, will be first enforced by theAPPaccording to the$attribute_info_typespeciffications and then enforced by theCREDENTIAL ISSUER API SERVICE, which will then will check wether the$attribute_info_valuesinputed by the user are present in the$attribute_info_value_set. For each pilot, those will be:- DDDC: String CODE + Email & array of permitted codes and array of permitted emails (strings both).
- IOT: String CODE + username & array of permitted codes and array of permitted usernames (strings both).
$credential_issuer_endpoint_address: API endpoint with exposed methods. There will be one credential issuer service per pilot, packaged in Docker files and deployed either by each pilot or by Dyne (as DDDC currently is).$credential_issuer_name: Name to identify who is providing verification for each credential (in this case, it will be DDDC (DDDC) and SmartCitizen (IoT) respectively).$credential_issuer_unique_id: Unique ID identifying theCREDENTIAL ISSUERassociated with the credential, the mapping between$credential_issuer_nameand$credential_issuer_unique_idis one to one.$credential_issuer_public_keys: Public keys generated by theCREDENTIAL ISSUERresponsible for distributing the credentials, there is one set of keys generated for each particularATTRIBUTE. TheCREDENTIAL ISSUERis responsible to track and map each pair of keys to each$authorizable_attribute_idwhich identifies theATTRIBUTEand its associated credentials.
- The attributes to obtain verification for will be in the pilots:
- DDDC: "I have right to participate in petition
$petition_id". - IoT: "I belong to community
$community_id.
Note that the mapping
$community_id-$petition_id-$autorizable_attribute_idis ONE TO ONE. In those notes, we will use$autorizable_attribute_idfor generality. Note also that those sentences need be added by string replacement hardcoded on the zenroom codes by the app at the start of the coconut flow. - DDDC: "I have right to participate in petition
- The
CREDENTIALwill be used for login into theBCNNOW DASHBOARDas well as to decide eligibility to participate in pilot:- DDDC: Right to sign petition in ledger for petition
$petition_id - IoT: Right to submit data to the encrypted data store for community
$community_id
- DDDC: Right to sign petition in ledger for petition
- For the special case of the DDDC pilot, the
CREDENTIALSwill be issued once per unique values of$attribute_info, to preserve uniqueness of petition signatures. This means two things:- If the user loses the credential, she will not be allowed to obtain new credentials
- **The
CREDENTIAL ISSUERneeds to keep track of the (HASHED)$attribute_inforeceived arrays, and DENY credentials if one credential has been issued already to a requestes$attribute_infoarray (in the DDDC, a pair ('email':'ula@ulahop.com', 'code':'X23455') for instance.
- API is implemented for a single attribute credential. Puria is working to adapt to the multiple petitions/communities case. In the following, we have the mapping:
·$petition_id / $community_id -> $authorizable_attribute_id -> $authorizable_attribute_credential_issuer_keypairs. That is, there is a keypair generated by the CREDENTIAL issuer perATTRIBUTE(identified by$authorizable_attribute_id).- It also means, that whenever we use credentials for authorization, for instance in the
BCNNOW DASHBOARD, the credential need to be passed along with meta data containing the$credential_issuer_endpoint_addressand the$authorizable_attribute_idin order for the VERIFIER (the DASBOARD in this case) to retreive the public keys and execute the zenroom verification script. See step 8 in COCONUT flow.
-
PILOT ADMINdefines anATTRIBUTEvia the set (variable)$autorizable_attribute_infofor which the credential issuer will be able to issue aCREDENTIALconfirming their validity for a participant in the Pilot. TheCREDENTIALwill validate theATTRIBUTEdefined above for each pilot. -
PILOT ADMINreceives a$credential_issuer_authorization_tokenwhich allows them to issue data creation requests to the credential issuer API service (defined by$credential_issuer_endpoint_address).
@Rohit Set here the step where PILOT ADMIN gets a token to communicate with Dashboard
-
PILOT ADMINmakes a POST call, including the$credential_issuer_authorization_tokenas an Authorization header to create a newAUTHORIZABLE_ATTRIBUTEsending over the defined attributes via a data structure called$authorizable_attribute_info. AnAUTHORIZABLE_ATTRIBUTEis a record stored by the credential issuer that defines theATTRIBUTESfor which the credential issuer will issue credentials. The API returns a$autorizable_attribute_idthat will be use to identify the credential associated with the attribute issued by this credential issuer. The request must include a special field$authorizable_attribute_uniquewhich is a Bool Value specifying if the credential issuer must keep track or not of the provided credentials (see below). For IoT case$authorizable_attribute_unique=Falseand for DDDC case$authorizable_attribute_unique=True. -
The credential service receives the POST request, verifies its validity and saves the record, and returns an
$authorizable_attribute_idwhich uniquely identifies the attribute/community and is mapped to the$autorizable_attribute_id, which is mapped respectively to the$community_idand$petition_idfor each pilot. Also, the credential issuer HASHES theathorizable_attribute_info_set(the set of valid values for the$authorizable_attribute_info), which will be used for census check. (In the pilot cases, a set of valid usernames/emails and a set of valid alphanumeric codes). Last but not least, the credential issuer service generates a PAIR of keys and stores them and assigns them to the$authorizable_attribute_id(step 3-4 of the COCONUT flow). It also creates a new endpoint$credential_issuer_endpoint_address/authorizable_attribute_idwhere you can get back in a public way via GET request the$authorizable_attribute_infotypes and keys (in our case, the field "email" and "code" and the type string) as well as the public keys needed to verify the credentials for this$authorizable_attribute_id(in our case, community/petition). -
(IoT speciffic) Community admin creates an
ENTITLEMENT POLICYand links it to a community, which defines a set of operations for the community. In addition to the configuration previously defined for a community, we also add a$credential_issuer_endpoint_address, the$authorizable_attribute_id, and the$authorizable_attributes_infofields. These fields are required so that the app knows how to obtain credentials for the community. This community is written to the policy store which stores the community configuration and creates a unique$community_idfor it. -
Community admin define name for community/petition, issues a post to Dashboards API and specifies the
ATTRIBUTEneeded to access each dashboard, identified by a$autorizable_attribute_idas well as a$community_id/petition_idand the$credential_issuer_endpoint_address. For both pilots it uses two different endpoints:
- IoT: Dashboard links it to
$autorizable_attribute_idnumber and gives public key back to community admin and a$bcn_now_community_id(for internal mapping to the attribute_id). - DDDC: Dashboard links it to
$autorizable_attribute_idnumber and a$bcn_now_community_id.
TO NOTE: A given
$community_id/petition_idcan be associated to one and only one$authorizable_attribute_id. Any service should be able to store and make this mapping ($community_id/petition_idto$policy_id[IOT case] toauthorizable_attribute_idtobcn_now_dashboard_idwith a DB via a many to one relationship table or something of the sort.
- Upon receiving a request, the
BCNNOW DASHBOARDparses the (authorized) request, and generates a$bcnnow_idmapped to each$community_id/petition_idwhich is mapped also to the$authorizable_attribute_id. It then queries the$credential_issuer_endpoint_address/$authorizable_attribute_idto obtain the public keys needed to verify credentials for the given petition/community.
- User goes through the onboarding application of SC which collects the geolocation and the exposure of the device.
- In the middle of the onboarding, user is prompted to install DECODE app as will be needed to complete flow.
- Onboarding application generates QR code containing the device token, geolocation and exposure and
$action=iot-onboardingso the APP knows what screen to show.
@ULA could you check this is ok? Example QR Code URI:
decodeapp://?action=iot-onboarding&device_token=1f5e66&latitude=&exposure=indoor&lat=41.396867&lng=2.194351Looks good to me. Should be validated by @jordi / @sam.
- App queries policystore for list of
$community_configvalues, that specify the available communities.The returned list contains the community description, its associated policy, a list of its operations and importantly the$credential_issuer_endpoint_address,$authorizable_attribute_idand$authorizable_attribute_infofields. - The user chooses a community to join with their device via app UI.
- App generates a keypair, step
01-CITIZEN-request-keypair.zencodein coconut flow. - App queries the
$credential_issuer_endpoint_address/$authorizable_attribute_idand gets information on the$authorizable_attribute_infofields and types. - App then presents a UI to the user that allows them to enter the values required for the
$authorizable_attribute_info. - User inputs the information and validates the types.
- At this point the app executes step
02-CITIZEN-request-blind-signature.zencodeof the coconut flow. Before this, it needs to string hard-core substitute the sentenceI declare that i belong to $community_id. - App issues a request to the
$credential_issuer_endpoint_addressi.e. a URL that uses the$authorizable_attribute_idto identify the attribute and including the$authorizable_attribute_infoin the request body as well as the output of step 2 of the COCONUT flow. - The credential issuer receives the request, parses the incoming data and does the following (case
$authorizable_attribute_unique=False):
- Checks each of the fields presented by the user are in the
$authorizable_attribute_info_set. If all are valid, then proceeds. Otherwise, throws an identification error back at the app. - If previous step is satisfactory, it executes step
05-CREDENTIAL_ISSUER-credential-blind-signature.zencodein the COCONUT flow. And returns the output to the app.
- App also executes the Zencode script (
07-CITIZEN-blind-proof-credential.zencode), which also is stored ready to be presented to anyone needed to check its validity. - App makes call to stream encoder component to create the new encrypted stream (as per existing IoT pilot flow)
For earlier notes and considerations, see pad.
- User installs DECODE App and sets up desired data.
- User goes to DDDC website visits petition she is interested in signing. Clicks on the link (mobile navigation) or scans QR (desktop navitaion).
- App is triggered, the QR encodes information about the petition via a
$petition_id. The app queries theDDDC GraphQL APIfor peittion info via the$petition_id. It gets back information about the peittion, in particular the$authorizable_attribute_idand$credential_issuer_endpoint_addressassociated with the petition. - The user is asked via APP UI to obtain a credential to participate in the petition. To which the user agrees.
- App generates a keypair, step
01-CITIZEN-request-keypair.zencodein coconut flow. - App queries the
$credential_issuer_endpoint_address/$authorizable_attribute_idand gets information on the$authorizable_attribute_infofields and types. - App then presents a UI to the user that allows them to enter the values required for the
$authorizable_attribute_info. - User inputs the information and validates the types.
- At this point the app executes step
02-CITIZEN-request-blind-signature.zencodeof the coconut flow. Before this, it needs to string hard-core substitute the sentenceI declare that i can participate in $petition_id. - App issues a request to the
$credential_issuer_endpoint_address(in the new method to be defined, which is a merge of the current methods/blind_signatureand/validate_attribute_info) i.e. a URL that uses the$authorizable_attribute_idto identify the attribute and including the$authorizable_attribute_infoin the request body as well as the output of step 2 of the COCONUT flow. - The credential issuer receives the request, parses the incoming data and does the following (case
$authorizable_attribute_unique=True):
- Checks each of the fields presented by the user are in the
$authorizable_attribute_info_set. If all are valid, then proceeds. Otherwise, throws an identification error back at the app. - Combines all of the inputed
$authorizable_attribute_infovalues and maps them via a HASH function to a$autorizable_attribute_info_value_hash. - It checks wether the
$autorizable_attribute_info_value_hashis on the Database of issued credentials. It it is, the credential is denied. It throws an error back to the app. - If it is not, it is stored on the DB as a an entry
$autorizable_attribute_info_value_hash:$timestamp. - If all previous steps are satisfactory, it executes step
05-CREDENTIAL_ISSUER-credential-blind-signature.zencodein the COCONUT flow. And returns the output to the app.
- App also executes the Zencode script (
07-CITIZEN-blind-proof-credential.zencode), which also is stored ready to be presented to anyone needed to check its validity.
-
The user goes to the BCNNow dashboard and attempts to access a restricted dashboard.
-
The BCNNow app knows the dashboard is restricted, so instead of showing the dashboard, redirects the user to a login screen that shows a QR code and has a message instructing the user to scan the QR code in order to login. This QR code defines a URL of the following form:
decodeapp://?sessionId=9876&callback=http://bcnnow.decodeproject.eu/wallet-login&action=login. If user is accessing from Mobile, the QR is a button with the same link.$sessionIdwould be a unique ID generated for every call to Login. -
The user opens their app, and scans the QR code, which set a
$action=loginor presses the button. -
The app displays a UI where the user can confirm they wish to share their credentials (each of which is associated with a
$authorizable_attribute_id) with the dashboard from a list of credentials. The user can also choose which data he/she wants to share with the dashboard to personalize her experience. -
If the user agrees, then the app sends a POST request back to the callback URL containing the previously created blind proof credential to the dashboard, as well as the reference
$authorizable_attribute_idand$credential_issuer_endpoint_address. It also contains extra information in a JSON file that allows to personalize the view.
Json structure to be shared by App team. The current API call and json structure is at the following doc https://docs.google.com/document/d/1oHHrE60Q5VCHumUO5Va1DbXDKKMY8aFSw9E6-zAH9Fk/edit?usp=sharing PLEASE agree in unified vision and open a repo and document there.
ROHIT please make this call asynchronous (get the keys and all of that)
-
The dashboard queries or gets from internal DB the credential issuer public keys associated with a given
$authorizable_attribute_idfrom the provided$credential_issuer_endpoint_address. The dashboard executes the Zencode script (08-VERIFIER-verify-blind-proof-credential.zencode), which is able to check that the blind credential is valid. This script requires a$autorizable_attribute_idpassed earlier by the app. The dashboard then queries the$credential_issuer_endpoint_addressand asks for the$validation_keysthat are the input of the needed script to validate the credentials. -
If the credential is valid then the dashboard creates a new session for the user, and logs them in, redirecting to the requested dashboard. Either on the same device (if it is on the phone) or via callback on the browser
Potentially add step 8. for log-in using a PC browser and an aPP to notify user all is good. @Jordi?
Source: https://docs.google.com/presentation/d/1UVeYiP4KQ2yFgUq6O2Y0NwE_g7kZfCKb6THeb3vYajg/edit
Authors: Oleguer Sagarra (Dribia) with edits from Sam Mulube (Thingful), and Rohit Kumar (Eurecat)