Tankar från vår verklighet.

Michael Dubell

Security recommendations for implementing BankID

Michael Dubell

BankID is the leading identification solution in Sweden that allows companies and government agencies to authenticate individuals over the Internet. BankID offers an API which makes integration easy for companies.

In this article I will describe BankID API features which developers should use to limit the effectiveness of today’s phishing attacks against BankID. I will also cover how QR codes can be used as a method for authentication/signing with mobile BankID and how it can improve security.

After reading this article, you will have learned different phishing techniques that exists and what you can do to limit their effectiveness.

Ordering shoes

Depending on which platform you initiate BankID on, the flow will be different.

Let’s assume we want to order a pair of shoes from on our computer. We pick our shoes, proceed to checkout, enter our address information and select mobile BankID as our signing method. We enter our personal identity number (PIN) and open the BankID app on our phone and sign.

What happened was that sent a signing order with our PIN to BankID using their REST API, informing that the accompanying PIN should sign this request. In this scenario, we expect the user to consume their signing order on a mobile device. I will later explain why this distinction is important. After we send this request to BankID, a special token called autoStartToken is created which is tied to our session. This token is returned to the user, depending on which BankID method is used.

The BankID API offers a requirement parameter which allows you to configure how orders should be created and verified. To configure an order to be limited to mobile BankID, set certificatePolicies in the requirement field:

"requirement": {    "certificatePolicies": ["1.2.752.78.1.5"]}

This restricts an order to only be consumed on mobile devices. The same can be done for other platforms. If it is not evident why it is beneficial to control how an order should be consumed, the following example will show why.

The autoStartToken

Let’s say implemented a member’s area page protected by BankID login, with the option to use BankID on file to authenticate. No personal identity number is technically required for this option, if you have multiple identities on your computer/phone, you will be prompted to select the appropriate identity.

Alright, we are sitting at our computer, we browse to the member’s area at and login by authenticating with BankID on file. What happens at this stage is that a special URL is returned to our browser which opens the BankID application automatically. The URL looks like this:


The local BankID application opens automatically because it has associated itself with the protocol bankid://. The interesting part is the autoStartToken parameter which contains the token value. This token is associated with your current session.

After your local BankID opens, you enter your credentials and successfully complete the identification (or signing). Now, let’s assume the developers at did not specify which platform the token should be limited to. This is means that even though you requested to identify/sign with BankID on file, the token you received can be consumed by mobile BankID on a different device. An attacker could generate a token meant for BankID on file and trick someone to authenticate themselves with the token on their mobile device.

The only thing an attacker needs to do is to send the following:


Which can of course be semi-disguised as an HTML link, like so:

<a href="bankid://?autostarttoken=463e5661-33a9-4738-ad1e-6c5ef1d732ce&redirect=null">Click me!</a>

Once the unknowing user clicks the link and identify using mobile BankID on their smartphone, the attacker will be successfully logged in as the user. Why this seemingly tiny detail matters is because most users today use mobile BankID which makes this scenario easy for an attacker to perform. Had the token been limited to only be consumed using BankID on file, then this scenario had not been possible. The only thing an attacker could do is to trick someone to identify with the token using specifically BankID on file, which is harder for an attacker to convince someone to do, since most people use mobile BankID.


In the first example we ordered shoes from from our computer, entered our personal identity number and chose to sign with mobile BankID. If you have multiple mobile devices with your BankID identity installed, you could open any of those devices to sign the request, which is the purpose of mobile BankID.

Let’s explore another common scenario – has created their own app which you have downloaded from the Appstore to your smartphone. In order to use the app, you must enter your PIN and login in using mobile BankID. Since you are on your smartphone and trying to login with your smartphone, you would expect only your smartphone to be able to authenticate. However, as previously mentioned if you have multiple devices with your BankID identity installed, any of them could open the BankID app the sign the request.

This becomes problematic because an attacker could enter your PIN and trick you into signing. This is how most BankID scams are performed today.

But as you may suspect, there is a way to control if all your devices should be able to sign a BankID request or if it should be limited to the device that initiated the request. This is done by specifying the autoStartTokenRequired field in the API request when creating an authentication/signing order request.

"requirement": {"autoStartTokenRequired": true}

The option autoStartTokenRequired specifies that no other device will be able to sign the request. Only the device that initiated the request (your smartphone in this case) will get the autoStartToken and thereby be able to sign with BankID. This means we can make it harder for those who enter other people’s personal identity number and tricks people into signing with their mobile BankID. By specifying autoStartTokenRequired, only the attacker will get the autoStartToken. The attacker must then somehow transfer the token to the victim.

The problem is that we can’t use autoStartTokenRequired when ordering on our computer and signing with mobile BankID, because our mobile phone somehow needs to consume the autoStartToken. This is where QR codes comes into play.

Scan the QR Code

QR code scanning does not involve implementing a new technology or support a new protocol, it’s already supported! The QR code is just a visual representation of the URL containing the autoStartToken.

The only thing developers need to do is to convert the returned URL after sending an authentication/signing order request to BankID, to a QR code and instruct the user to scan it with their mobile BankID, that’s it!

We previously mentioned the autoStartTokenRequired option and its purpose to only allow the device with the autoStartToken to authenticate/sign an order request. This works great if you are using BankID on file on your computer/smartphone or mobile BankID on the same device. However, it will not work if you are using mobile BankID on different devices, since you often initiate the request on your computer and open the mobile BankID app on your phone. The token cannot be created with autoStartTokenRequired = True in this scenario. This is where QR codes shines.

The QR code is just a visual representation of


Which now means that the user can easily consume the autoStartToken and sign the request.

Which is the ingredient you need to authenticate/sign with BankID. Therefore, when offering to sign with mobile BankID on a different device, autoStartTokenRequired can be set to True if QR codes are used.


We have identified three possible flows using BankID

  • BankID on file
  • Mobile BankID – different device
  • Mobile BankID – same device

To make current phishing attacks against BankID harder to perform, we can do the following:

  • Set certificatePolicies to define which platform an authentication/signing order request should be limited to.
  • To prevent our mobile BankID app to automatically activate when there is an existing authentication/signing request order present, we can set autoStartTokenRequired = True. Good for BankID on file and mobile BankID on same device.
  • When using mobile BankID on different devices – set autoStartTokenRequired = True and enable QR codes. The user must scan the QR code presented on the device that initiated the order request.
  • The user’s personal identity number should always be present for each order request. This limits the effectiveness of simply generating a token and sending it to random people, hoping that someone will sign using the token.

None of these features prevents phishing attacks against BankID. They only make today’s attacks harder to perform and requires additional technical skill from the attacker than just being able to call victims. If the attacker can trick a victim into clicking a link containing the autoStartToken, it will be possible to phish BankID users.

However, the point is to make the process more difficult for the attacker, which can be achieved by following the steps above.

BankID API documentation can be found here:

Bonus question: Can you find the open redirection in the token URL? :)