If you want to try out a simple example using a verifiable credential for a passwordless login to your web service, you can start with an example code available on Github. It's a simple node.js based web service which integrates sideos for a passwordless login.
The example should help you to understand the basic flow of issuing and verifying a credential. Let's start with downloading the sideos wallet and setting up the web service that will interact with the user.
Get the sideos Wallet
First, you need do get the sideos wallet to get started. You can install the sideos wallet from Google Play or Apple's App Store.
Once you've installed the wallet proceed below.
Setting up a Web Service
Make sure you have Node.js (>18) and yarn installed. There are plenty of instructions available in the internet to help you install Node.js on your system.
We have prepared a trial ACCESS_TOKEN and a credential template (LOGIN_TEMPLATE_ID=63) that you will need to access the sideos API for issuance and verification of credentials. To generate your own access token and to create your own credential templates you can open an account on the sideos console for free.
To use it in the example service, create an .env file to the root folder of the repository and add the following content:
The CALLBACK_URL is an API endpoint of your web service to which the wallet sends responses and shared credentials. That needs to be changed to your individual environment. The DID_ISSUER is the id of the trial account wallet and will be used to validate the credential.
The example is using redis as a session storage. To install redis on a Linux-based machine, e.g. using Ubuntu you install and setup the redis server as a system service with the following commands:
Change into the example code folder and install the node packages with
yarn install
and start the server with yarn:
yarn start:dev
The output should be something like this below:
yarn start:dev
yarn run v1.22.21
$ nodemon src/index.ts
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**/*
[nodemon] watching extensions: ts,json
[nodemon] starting `ts-node ./src/index.ts src/index.ts`
Server started at http://MacBook-Work.local:9000
Redis Client connected...
Redis Client ready
Issue a Verifiable Credential to Your Wallet
The example web service provides a path to issue a credential. With your browser navigate to http://<your IP/hostname>:9000/issue to generate a credential offer and capture the credential in your wallet.
If you scan the QR Code with the sideos wallet you will see the screen below to accept the credential offer and store it on your phone. If you select the credential and click in CONFIRM the credential is stored on your phone.
The code to create a issue endpoint to show the QR Code on the frontend is shown below:
If you accept the offer the wallet send the confirmation back to the callback url. The web service then knows the credential was accepted and can initiate some completion process.
The example code for the callback endpoint is shown below:
exportconstpostConsumeCredentialOffer=async (req:Request, res:Response, next:NextFunction) => {constredisClient=createClient({ legacyMode:true })awaitredisClient.connect().catch(console.error)try {constjwt=req.body.jwt;let authToken:string=req.params.token;if (!authToken &&req.query.challenge) { authToken = <string>req.query.challenge }console.log('Consume Offer challenge parameter:', authToken)let vcs:Array<any> = [];constresponse=awaitaxios.post(process.env.SSI_SERVER+'/v3/consumeoffer', { template:process.env.TEMPLATE_ID, token: jwt }, { headers: {'Content-Type':'application/json','X-Token':process.env.ACCESS_TOKEN } })constres_jwt=response.data.data.jwtconstdecoded:any=decodeJwt(res_jwt);decoded.verifiableCredential.forEach((element:any) => {vcs.push(element) });console.log('Trusted DID_ISSUER: ',process.env.DID_ISSUER);console.log('email: ', vcs[0].credentialSubject.Email);console.log('Name: ', vcs[0].credentialSubject.name);console.log('did: ', vcs[0].credentialSubject.id);console.log('issuer_did: ', vcs[0].issuer.id);if(vcs[0].issuer.id ===process.env.DID_ISSUER&& vcs[0].credentialSubject.id) {constdid= vcs[0].credentialSubject.id;constsession_id=awaitredisClient.v4.get('chid:'+authToken)awaitredisClient.v4.del('chid:'+authToken)awaitredisClient.set('user:'+ did,JSON.stringify({did: did, name: vcs[0].credentialSubject.name, issuer: vcs[0].issuer.name}))console.log(session_id)// here: send VC data relevant for the FE back in the response via websocketconstws=getSocket(session_id); if(ws) {console.log('Socket found for ', session_id)ws.send(JSON.stringify({ error:0, registrationComplete:true, did: did, email: vcs[0].credentialSubject.Email, name: vcs[0].credentialSubject.name, role: vcs[0].credentialSubject.Role, })) } }returnres.status(200).json(response.data) } catch (err) {console.log(err)returnres.status(403).send('Access denied, invalid VC') }}
Login with a Verifiable Credential
With your browser navigate to http://<your IP/hostname>:9000/ . The web service loads the login page and shows a QR Code that you scan with the sideos wallet.
The code that generates the QR Code fetches the data for the request from the sideos API and creates a unique request for a login credential of the type "User". If you have that credential type stored in your wallet the wallet asks you to share the credential with the web service:
The code to create a login endpoint to show the QR Code on the frontend and store the session in redis is rather small:
The response from the wallet is send to the callback url which was embedded into the credential request. The function behind the endpoint is postLoginConsumeReqest(). This piece of code does the whole work of the user authentication. It checks if the credential is valid by sending it to the validation endpoint of the sideos API, checks if the issuer of the credential can be trusted - we set this part in the .env file as DID_ISSUER - and if there is a subject in the credential which holds the data elements we want to use in the web service, eventually.