Repository navigation
Tutorials
- TBD
Web eID allows to have controlled access to a client side smart card/reader from a website. The general workflow should be familiar to anyone with experience with a PC/SC level interface, either directly with SCard* functions or javax.smartcardio or Android IsoDep. The main difference is absence of "discovery methods" that allow the uncontrolled enumeration of readers and the security restriction of sending ISO 7816-4 APDU-s that contain a plain text PIN, a restriction enforced with secure smart card readers with a PIN firewall (search page for "firewall").
The general workflow goes as follows:
- ask the user for a card/reader to use and establish a connection to it with
webeid.connect(). The user experience depends on client hardware and adapts to changes, as seen on this small screencast - transceive any APDU-s as necessary, with
Reader.transmit() - close the connection with
Reader.disconnect()
While not yet enforced and implemented, ISO 7816-4 conforming APDU-s that deal with PIN related tasks (0x20 VERIFY, 0x24 CHANGE REFERENCE DATA, 0x2C RESET RETRY COUNTER) shall be blocked and associated Reader.verifyPIN() and Reader.modifyPIN() have to be used, with input parameters from PC/SC v2 part 10, which translates to CCID v1.10 section 8 in real life.
Here is a commented sample for accessing a smart card reader to run multiple APDU-s against a card
const webeid = require('web-eid') // assumes a packager like Webpack or Rollup
// Check for availability of Web eID functionality
webeid.isAvailable().then(function(available) {
// available will be false if Web eID is not available
if (!available) {
window.location.href = 'https://web-eid.com/app/'
} else {
// Web eID is available and functioning.
// Ask the user for a smart card. If you know the ATR-s of the cards of interest, add them to
// the atrs array. If you need to connect with a specific protocol, specify it instead of the default '*'
webeid.connect({atrs: [], protocol: '*', timeout: 60}).then(function(reader) {
// You will have the information about the chosen reader available
console.log('Connected to', reader.name, 'with protocol', reader.protocol)
// Send a simple "SELECT FILE MF" APDU to the chosen card
reader.transmit(Buffer.from('00A4000C00', 'hex')).then(function(response) {
console.log('Card replied', Buffer.from(response).toString('hex'))
reaer.disconnect() // disconnect the reader cleanly
}).catch(function(reason) {
console.log('Transmit failed', reason.message)
reader.disconnect() // disconnect the reader, even if it would be a no-op after a technical error
})
}).catch(function(reason) {
// the message of the Error object will be an error code from PC/SC
console.error('Could not establish connection to a smart card reader:', reason.message)
})
}
})