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 submodule
trick). - 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
BCNNOW
and theCREDENTIAL ISSUER API SERVICE
following the rules accorded with the respective users in off-line sessions. This admin needs a$bcnnow-api-token
and a$ci-api-token
to 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
ATTRIBUTE
which will require to be verified in order to participate in the pilots. ThoseATTRIBUTES
will 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 theAPP
according to the$attribute_info_type
speciffications and then enforced by theCREDENTIAL ISSUER API SERVICE
, which will then will check wether the$attribute_info_values
inputed 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 ISSUER
associated with the credential, the mapping between$credential_issuer_name
and$credential_issuer_unique_id
is one to one.$credential_issuer_public_keys
: Public keys generated by theCREDENTIAL ISSUER
responsible for distributing the credentials, there is one set of keys generated for each particularATTRIBUTE
. TheCREDENTIAL ISSUER
is responsible to track and map each pair of keys to each$authorizable_attribute_id
which identifies theATTRIBUTE
and 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_id
is ONE TO ONE. In those notes, we will use$autorizable_attribute_id
for 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
CREDENTIAL
will be used for login into theBCNNOW DASHBOARD
as 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
CREDENTIALS
will 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 ISSUER
needs to keep track of the (HASHED)$attribute_info
received arrays, and DENY credentials if one credential has been issued already to a requestes$attribute_info
array (in the DDDC, a pair ('email':'[email protected]', '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_address
and the$authorizable_attribute_id
in 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 ADMIN
defines anATTRIBUTE
via the set (variable)$autorizable_attribute_info
for which the credential issuer will be able to issue aCREDENTIAL
confirming their validity for a participant in the Pilot. TheCREDENTIAL
will validate theATTRIBUTE
defined above for each pilot. -
PILOT ADMIN
receives a$credential_issuer_authorization_token
which 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 ADMIN
makes a POST call, including the$credential_issuer_authorization_token
as an Authorization header to create a newAUTHORIZABLE_ATTRIBUTE
sending over the defined attributes via a data structure called$authorizable_attribute_info
. AnAUTHORIZABLE_ATTRIBUTE
is a record stored by the credential issuer that defines theATTRIBUTES
for which the credential issuer will issue credentials. The API returns a$autorizable_attribute_id
that 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_unique
which 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=False
and 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_id
which uniquely identifies the attribute/community and is mapped to the$autorizable_attribute_id
, which is mapped respectively to the$community_id
and$petition_id
for 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_id
where you can get back in a public way via GET request the$authorizable_attribute_info
types 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 POLICY
and 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_info
fields. 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_id
for it. -
Community admin define name for community/petition, issues a post to Dashboards API and specifies the
ATTRIBUTE
needed to access each dashboard, identified by a$autorizable_attribute_id
as well as a$community_id/petition_id
and the$credential_issuer_endpoint_address
. For both pilots it uses two different endpoints:
- IoT: Dashboard links it to
$autorizable_attribute_id
number 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_id
number and a$bcn_now_community_id
.
TO NOTE: A given
$community_id/petition_id
can be associated to one and only one$authorizable_attribute_id
. Any service should be able to store and make this mapping ($community_id/petition_id
to$policy_id
[IOT case] toauthorizable_attribute_id
tobcn_now_dashboard_id
with a DB via a many to one relationship table or something of the sort.
- Upon receiving a request, the
BCNNOW DASHBOARD
parses the (authorized) request, and generates a$bcnnow_id
mapped to each$community_id/petition_id
which is mapped also to the$authorizable_attribute_id
. It then queries the$credential_issuer_endpoint_address/$authorizable_attribute_id
to 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-onboarding
so 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.194351
Looks good to me. Should be validated by @jordi / @sam.
- App queries policystore for list of
$community_config
values, 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_id
and$authorizable_attribute_info
fields. - The user chooses a community to join with their device via app UI.
- App generates a keypair, step
01-CITIZEN-request-keypair.zencode
in coconut flow. - App queries the
$credential_issuer_endpoint_address/$authorizable_attribute_id
and gets information on the$authorizable_attribute_info
fields 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.zencode
of 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_address
i.e. a URL that uses the$authorizable_attribute_id
to identify the attribute and including the$authorizable_attribute_info
in 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.zencode
in 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 API
for peittion info via the$petition_id
. It gets back information about the peittion, in particular the$authorizable_attribute_id
and$credential_issuer_endpoint_address
associated 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.zencode
in coconut flow. - App queries the
$credential_issuer_endpoint_address/$authorizable_attribute_id
and gets information on the$authorizable_attribute_info
fields 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.zencode
of 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_signature
and/validate_attribute_info
) i.e. a URL that uses the$authorizable_attribute_id
to identify the attribute and including the$authorizable_attribute_info
in 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_info
values and maps them via a HASH function to a$autorizable_attribute_info_value_hash
. - It checks wether the
$autorizable_attribute_info_value_hash
is 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.zencode
in 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.$sessionId
would be a unique ID generated for every call to Login. -
The user opens their app, and scans the QR code, which set a
$action=login
or 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_id
and$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_id
from 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_id
passed earlier by the app. The dashboard then queries the$credential_issuer_endpoint_address
and asks for the$validation_keys
that 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)