BankID Integration
BankID Integration
Permalink to "BankID Integration"In one of the mobile app project in Centralsoft we had the need and the request to implement the authentication using the Bank ID service. Today we will talk and describe our journey to the success of BankID integration.
What is BankID?
Permalink to "What is BankID?"BankID is by far the largest electronic identification system in Sweden, with a usage rate of 94% among smartphone users, and is administered by Finansiell ID-Teknik BID AB that is owned by several Swedish and Scandinavian banks. Individuals who have a Swedish personnummer (Swedish national identification number) can obtain Swedish BankID through their bank. A BankID has the same value and is used the same way, regardless of the bank that issued it.
Swedish national identification number?
Permalink to "Swedish national identification number?"The personal identity number (personnnummer) is the Swedish national identification number. It is a ten or twelve-digit number that is widely used in Sweden to identify individuals. It is constructed from some personal parameters which give this number some special information about your identity.
Integration of BankID
Permalink to "Integration of BankID"BankID has a public API which we can consume in two different environments:
- Test
- Production
When developing and testing you should use the test environment. To be able to use the test environment you will need:
-
An SSL certificate for identification with the BankID web service API. https://www.bankid.com/en/utvecklare/test Passphrase for this certificate: qwerty123
-
The URL for BankID’s web service API. https://appapi2.test.bankid.com/rp/v5.1
-
Trust the issuer of the SSL certificate.
-
A test version of the BankID app
-
Download cert bundles: https://ufile.io/fcj4eykh
Installation:
Permalink to "Installation:"Android: https://play.google.com/store/apps/details?id=com.bankid.bus&hl=en&gl=US iOS: https://apps.apple.com/se/app/bankid-säkerhetsapp/id433151512 Even after installing the application you need to perform some other configurations for the BankID application to work in the test environment
Configuration
Permalink to "Configuration"iOS:
- In Settings → BankID → Developer → Server , enter cavainternal.test.bankid.com .
Android:
- Put phone to Airplane Mode
- Open the BankID App and Settings in the BankID app and select About BankID
- Make a "long press" (ie press and hold) on the heading Error information .
- Enter kundtest in the box that appears and press OK
- Without leaving About BankID, check that it says CUST after version number. This verifies that you entered correctly.
Note:\
- App must be uninstalled / reinstalled to be restored to the production environment. \
- The BankID app cannot be run in emulated environments. (simulators won’t work)
- A BankID for test.
Go to www.demo.bankid.com You’ll see a section “Login with a personal code”
Fill the required fields. As for email please be aware that Gmail, Outlook providers might not work so in that case use your company email (example: info@centralsoft.io)
Check the email and get the code
Go back again to www.demo.bankid.com use your code and login.
Let’s issue BankID for test
You will need to fill details and also a swedish personal number. To generate one we can use this online generator: https://tedeh.net/tools/generator-for-swedish-personnummer/ You should delete the dash (-) from the generated number.
Then open BankID issuing
A new window will open with an animated QR-code which we will scan through the mobile bankID app
Let’s open the mobile app and let’s press the QR code button and scan the QR code. After that we will need to set a security code (imagine this as a bankID password). Finally we will have the account completed and we can start using it.
Development
Permalink to "Development"Development
For the backend part we will use NodeJS.
Let’s create a service that handles all the needs for the BankID.
We have to configure a request agent to use the SSL client certificate provided by BankID. This can happen easily using Axios package.
npm install axios
npm i await-to-js
Setting up the agent
Permalink to "Setting up the agent"const axiosLib = require('axios');
const fs = require('fs');
const https = require('https');
const to = require('await-to-js').to;
const config = {
mobileBankIdPolicy: '1.2.3.4.25',
bankdIdUrl: 'https://appapi2.test.bankid.com/rp/v5',
pfx: fs.readFileSync('./certs/FPTestcert2_20150818_102329.pfx'),
passphrase: 'qwerty123',
ca: fs.readFileSync(`./certs/test.ca`),
};
// Agent for using SSL client certificate
const axios = axiosLib.create({
httpsAgent: new https.Agent({
pfx: config.pfx,
passphrase: config.passphrase,
ca: config.ca,
}),
headers: {
'Content-Type': 'application/json',
},
});
After setting up the agent we’re ready to start making BankID API calls but also we should remember some bullet points:
- All calls are made using HTTP POST method
- We must include header: Content-Type: application/json
- All of the parameters should be sent as JSON in req.body
After setting up the agent we’re ready to start making BankID API calls but also we should remember some bullet points:
- All calls are made using HTTP POST method
- We must include header: Content-Type: application/json
- All of the parameters should be sent as JSON in req.body
Setting up a wrapper for API calls
Permalink to "Setting up a wrapper for API calls"async function call (method, params) {
const [error, result] = await to(
axios.post(`${config.bankdIdUrl}/${method}`, params));
if (error) {
// You will want to implement your own error handling here
console.error('Error in call');
if (error.response && error.response.data) {
console.error(error.response.data);
if (error.response.data.errorCode === 'alreadyInProgress') {
console.error('You would have had to call cancel on this orderRef before retrying');
console.error('The order should now have been automatically cancelled by this premature retry');
}
}
return {error};
}
return result.data;
}
For error handling please refer to this official BankID api documentation (section 6)
https://www.bankid.com/assets/bankid/rp/BankID-Relying-Party-Guidelines-v3.7.pdf
BankID Auth method call
Permalink to "BankID Auth method call"To initiate authentication, call the auth
endpoint (for example https://appapi2.test.bankid.com/rp/v5/auth
) with the following parameters
Making this call will trigger the authorization flow in the users BankID app.
const auth = async (endUserIp: any) =>
await call('auth', {
endUserIp,
requirement: {
allowFingerprint: true,
},
})
Response: (we will need the orderRef and autoStartToken)
{
"orderRef": "3efa7e6a-6ee6-426b-b4be-e18f24b4738c",
"autoStartToken": "3575439f-b003-470f-b5c0-fa9c00650e17",
"qrStartToken": "08f70922-8428-4335-81fe-643f4a96ec49",
"qrStartSecret": "9f413434-4ad7-43d5-8c51-5acc8c597f14"
}
autoStartToken
be used to construct a url that can be launched on the users device and picked up by the BankID app, if it is installed.
iOS: https://app.bankid.com/?autostarttoken=[AUTOSTART_TOKEN_HERE]&redirect=null
Other devices: bankid:///?autostarttoken=[AUTOSTART_TOKEN_HERE]&redirect=null
The brackets around the autoStartToken should be included.
BankID polling for results (ongoing order)
Permalink to "BankID polling for results (ongoing order)"You will need to poll the collect
method to retrieve the status of an ongoing operation.
As refering to the BankID official documentation, it states that we should call collect every two seconds but specifically not more often than once per second
The collect
method takes a single parameter – orderRef
– and returns two out of three values: status
, hintCode
and completionData
.
const collect = async (orderRef: any) => await call('collect', { orderRef })
const startPolling = async (orderRef: any) => {
try {
while (true) {
const {status, hintCode, completionData} = await collect(orderRef);
if (status === 'failed') {
return {ok: false, status: hintCode};
} else if (status === 'complete') {
return {ok: true, status: completionData};
} else {
console.log(hintCode);
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
} catch (err) {
return err
}
}