oddhill/node-bankid

The demo code could be more complete

Opened this issue · 2 comments

Excellent module! But the documentation and demo code leaves a lot to desire.
So here's my suggestion for the demo app (know of any err.status or result.progressStatus codes I've missed?):

'use strict';

// Note that this example code was designed to be run directly from this
// folder, some values may have to be changed if you copy and paste this
// code into your own project.

const path = require('path');
const bankid = require('../lib/index');

const options = {
  pfx: path.resolve('../certs/FPTestcert2_20150818_102329.pfx'),
  passphrase: 'qwerty123',
  env: 'test',
};

const authOptions = { personalNumber: "" };

if(!authOptions.personalNumber) {
  console.log("Before using this demo, edit the implementation to specify a personalNumber to authenticate.");
  console.log("To install a test-environment certificate, see https://www.bankid.com/assets/bankid/rp/how-to-get-bankid-for-test-v1.5.pdf");
  process.exit();
}

function handleError (err) {
  switch(err.status) {
    case 'ALREADY_IN_PROGRESS': {
      console.log(`An operation is already underway. Cancel (or complete) it in the BankID app and try again.`);
    } break;
    case 'USER_CANCEL': {
      console.log(`The user cancelled the operation.`);
    } break;
    case 'EXPIRED_TRANSACTION': {
      console.log(`Time-out. The user did not complete the identification process.`);
    } break;
    case 'CERTIFICATE_ERR': {
      console.log(`Authentication failed. The user probably entered the wrong PIN-code too many times!`);
    } break;
    case 'INVALID_PARAMETERS': {
      console.log(`The BankID API was called with invalid parameters (e.g. an expired orderRef).`);
    } break;
    default: {
      if(err.message == 'The specified social security number must be 12 digits in length.') {
        console.log(err.message);
      } else {
        console.log("ERROR:", JSON.stringify(err, null, 2));
        console.log(err.stack);
      }
    }
  } 
}

// This example shows how to use the bankid module to create a new service instance that
// can be used to then access the BankID API-endpoints.
bankid(options, (err, service) => {
  if(err) return handleError(err);

  service.authenticate(authOptions, (err, response) => {
    if(err) {
      handleError(err);
      process.exit();
    }

    console.log(`Authentication attempt started.`);
    console.log(`BankID app autoStartToken: ${response.autoStartToken}`);
    
    console.log(`\nStarting polling authentication status using orderRef: ${response.orderRef}`)
    setInterval(function() {
      service.collect(response.orderRef, (err, result, rawSoapResponse, soapHeader) => {
        if(err) {
          handleError(err);
          process.exit();
        }
        
        switch(result.progressStatus) {
          case 'USER_SIGN': {
            console.log(`Waiting for ${authOptions.personalNumber} to enter the PIN-code...`);
          } break;
          case 'OUTSTANDING_TRANSACTION': {
            console.log(`The BankID app is unavailabe (e.g. busy showing an error message). Please attend it...`);
          } break;
          case 'NO_CLIENT': {
            console.log(`No online BankID app could be found. Waiting...`);
          } break;
          case 'COMPLETE': {
            const {name, givenName, surname, personalNumber, notBefore, notAfter, ipAddress} = result.userInfo;
            console.log(`\n${name} (${personalNumber}) at ${ipAddress} was successfully authenticated!`);
            console.log(`\nsignature: ${result.signature}`);
            console.log(`\nocspResponse: ${result.ocspResponse}`);
            process.exit();
          } break;
          default: {
            console.log(`Got unexpected BankID progressStatus`);
            console.log(JSON.stringify(result, null, 2));
          }
        }
      });
    }, 1000);
  });

});

It's quite unfortunate that there's no 'status' code for the error that occurs when the personalNumber is invalid...

I'll have to think about this. I'm not sure i want to have full examples of how people should write their code but i do agree that the examples could be slightly better.

But i do not have a lot of time to work on this project so the current examples might have to be enough for a while.

I'm open to adding better error handling to the package like suggested in #3, something like the error handler you did that creates custom errors would be cool.