alliander-opensource / diva-irma-js

SDK for easy integration of IRMA into projects
BSD 3-Clause "New" or "Revised" License
4 stars 3 forks source link

diva-irma-js

This repository contains the DIVA JavaScript SDK. DIVA is an SDK to easily integrate IRMA attributes into NodeJS based applications.

Overview

This library consists of the following parts, which can work independent from each other:

Example / reference implementation

For a full starter project that shows how to use the three core components with examples, see the DIVA js Reference Third Party Backend

Usage

First add diva-irma-js as a dependency

npm install diva-irma-js --save

Then import/require the relevant Diva components:

Quick start guide: verifying an attribute

See the API reference below for more details and points on each step. Also, see (the DIVA js Reference Third Party Backend for an example).

First initialize diva-irma-js/session:

    const divaSession = require('diva-irma-js/session');
    const divaStateOptions = { useRedis: false };
    divaSession.init(divaStateOptions);

After initialising the Diva session module, import the diva library and set an IRMA Api Server (see below for options on how to do this).

    const diva = require('diva-irma-js');
    const divaOptions = {
       ...divaStateOptions                       // See above
      jwtDisclosureRequestOptions: {
        algorithm: 'none',
        issuer: 'diva',
      },
      jwtSignatureRequestOptions: {
        algorithm: 'none',
        issuer: 'diva',
      },
      jwtIssueRequestOptions: {
        algorithm: 'none',
        issuer: 'diva',
      },
      irmaApiServerUrl: 'http://FILL_IN:8080',
      irmaApiServerPublicKey: `-----BEGIN PUBLIC KEY-----
    FILL_IN
    `,
    };
    diva.init(divaOptions);

Now we can request a new disclosure session for a street attribute:

    const divaSessionId = 'foobar';   // This can be any string: use this to integrate diva-irma-js into your own session management system!
    diva.startDisclosureSession(['irma-demo.MijnOverheid.address.street'], 'Test label', divaSessionId)
      .then(irmaSessionInfo => ...);

irmaSessionInfo contains the string irmaSessionId and a qrContent object that needs to be converted to a QR code. The QR code can be scanned by the IRMA app.

After the QR code has been shown to the user, we can poll the IRMA api server for the current status:

     diva.getIrmaStatus('DISCLOSE', irmaSessionId)
       .then(irmaStatus => ...);

See below for possible statuses. After irmaStatus.serverStatus is 'DONE', we can retrieve the proof and add it to the IRMA session:

    if (irmaStatus.serverStatus === 'DONE') {
      divaSession.addAttributesFromProof(irmaStatus.disclosureProofResult, irmaSessionId);
    }

Now we can retrieve the disclosed attributes using the divaSessionId we defined earlier:

  getAttributes(divaSessionId)
    .then(attributes => ...)

You now have a working Diva installation!

Troubleshooting

If it does not work for some reason, first try to increase the log level by passing logLevel: 'DEBUG' to the divaOptions. Hopefully this will print some useful error messages. Also, looking at the IRMA Api Server logs can help sometimes.

API reference

diva-irma-js/session

This module is used for session storage of IRMA sessions. It uses in-mem or Redis for storage using diva-irma-js/state.

This module is initialized in the following way:

    const divaSession = require('diva-irma-js/session'); // Import this modulule
    const divaStateOptions = {};                         // See below
    divaSession.init(divaStateOptions);                  // Init module (this will create the actual in-mem or Redis store)

divaStateOptions

The following options can be passed to divaState:

IRMA vs Diva session

In diva-irma-js/state, we manage two type of sessions: IRMA sessions and Diva sessions. IRMA sessions are short-lived, and only exist in one IRMA interactive proof. These sessions are used by the IRMA Api Server and are also passed to the user via a QR code.

Diva sessions are more long-term and can for instance be bound to a specific browser/user via an HTTP cookie (the DIVA js Reference Third Party does this for example). Attributes disclosed in IRMA sessions can be bound to a Diva session. Also pending and failed IRMA sessions can be bound to a Diva session. This way, we can store a log of executed IRMA actions of a user.

Exposed functions:

BASIC functions:

Advanced functions: (normally not needed outside diva-js):

diva-irma-js/express

Diva-irma-js/express can be used to protect endpoints, and only return them if a user has disclosed the specified attributes. This module depends on a correctly initialized diva-irma-js/session library, see above on how to do that.

After that, this library can be imported in the following way:

    const divaExpress = require('diva-irma-js/express');

Then, endpoints can be protected in the following way:

    app.use('/api/endpoint/to/protect', divaExpress.requireAttributes(divaSession, ['irma-demo.MijnOverheid.address.street']), require('./actions/protected-endpoint'));

In this way, /api/endpont/to/protect can only be visited if a user had disclosed its street attribute.

diva-irma-js

The core library is used for communication with the IRMA Api Server. It therefore requires a working IRMA Api Server.

To run your own local IRMA Api Server, see its README. We recommend running it with Docker, because that saves a lot of configuration. The 'Running With Docker tutorial' also shows a script that will generate the required public key.

This module depends on diva-irma-js/state, and therefore depends on the diva-irma-js/session options, see above.

    const diva = require('diva-irma-js');       // Import diva library
    const divaStateOptions = {};                // divaStateOptions are needed here as well, see above
    const divaOptions = {                       // Options for ApiServer communication, see below
      ...divaStateOptions
    };
    diva.init(divaOptions);                     // Init Diva library

divaOptions

Exposed functions:

See the DIVA js Reference Third Party for an example implementation of all the functions exposed functions.

version() will return the currently running Diva library version.

Starting an IRMA session:

Use one of these three functions to respectively starts a disclosure, signing or issuing session. All these functions return an irmaSessionData object, which needs to be passed to the user in the form of a QR code.

Polling the status of a running session::

Use getIrmaStatus(irmaSessionType, irmaSessionId) to retrieve the session status of a running IRMA session.

This function will return an irmaSessionStatus and a serverStatus.

ServerStatus is the status that is returned by the IRMA Api Server, which can be:

IrmaSessionStatus is Diva's own locally cached version of the ServerStatus (mainly to prevent NOT_FOUND after the session is done):

IRMA

For more information about IRMA, see: https://privacybydesign.foundation/irma/

The IRMA client apps can be downloaded from their respective app stores:

Other components in the IRMA ecosystem include: