LinOTP's Rollout Token Feature

This how-to describes a typical use case of the rollout token feature and the required configuration steps.

It's about security...

Multi Factor is about security and so is every step involved. The authentication procedure, the seed storage, encrypted communication protocols. The overall security is just as weak as the weakest point in the process.

The Enrollment Process

One important step is the enrollment or assignment of tokens. So let's assume the user should use OATH soft token. The seed must be placed on the user's mobile. Typically this is achieved by scanning a QR code which contains the shared secret. For security reasons only the user itself should ever see this QR code so it is very sensible that the user enrolls the token himself without any involment of a third party like help desk employees.

LinOTP Self Service Portal

LinOTP provides for this purpose the self service portal. Although the actions - like token enrollment - can be limited to local network clients it might be necessary that users from untrusted networks can enroll their tokens as well. By default the username and the user password are requrired to log in to the self service portal. This would mean that the enrollment of the second factor depends on the knowledge of the first one. No clean separation and a possible weak link which could be exploited by an attacker. In order to prevent this attack vector the self service should be protected with a second factor. This is very sane and can be configured easily in LinOTP.

The Problem

But wait - what should a user do at the MFA login of the self-service if he does not have a token yet? He wants to roll out his token via the self-service portal first! What if he, as a remote user, can only reach the self-service portal via a VPN? The VPN is of course also protected with MFA.

The Solution - an exclusive rollout token

The user needs a token that can only be used to log in to the self-service portal and selected access points (e.g., VPN), but not for any other type of authentication.

This is the rollout token.

Any type of token can be used for this purpose - but when created, the token will by default be declared for self-service only. For example, an IAM system could create a static password token during the user onboarding process and mark it as a rollout token. This password is delivered to the user via a secure channel (e.g., encrypted email). The user logs in to the self-service portal with username, password and OTP and registers the actual token.

If necessary, the rollout token can additionally be allowed for validation at the VPN, for example.

Now the enrollment procedure is better secured. An attacker would need to have access to the password of the user and the encrypted e-mail. It would also be possible to print the OTP-password and hand it personally or via mail to the user or tell the user via phone. In the unlikely case the attacker steals the rollout token it can not be used for any authentication except the self service portal which is addionally secured with the users normal credentials.

As stated before every type of token can be used as rollout token. So be it a soft token, a SMS token or even Yubikey which is sent back by the user after the rollout procedure.

How to appoint a rollout token

Every token can be declared as rollout token. For sake of simplicity we will use a static password token. This token is enrolled via API and a parameter "rollout" or "scope=" is added to the API call.


This parameter is the magic key - it can be combined with any token during enrollment in order to make this token a rollout token.
# simply a rollout token for logging in to the self service

https://LINOTP/admin/init?user=USER&realm=NAME&type=PW&otpkey=PASSWORD \

# create rollout tokens for self-service login and validation

https://LINOTP/admin/init?user=USER&realm=NAME&type=PW&otpkey=PASSWORD \
&description=DESCRIPTION&scope={"path":["userservice", "validate"]}&session=COOKIE

Explanation of the URL components:

This is the IP or FQDN of the LinOTP server
The controller used for enrollement (and a lot of other interesting staff:
user [optional]
Name of the user for whom the token is enrolled. The token can also be enrolled without a user name and assigned later.
The type of the enrolled token. Different types of token require different additional options.
This parameter contains the password which acts as OTP. This is a specific parameter for tokens of the type "PW"
description [optional]
The description will be displayed in the token management GUI. If it is left out it will contain "rollout token".
rollout [optional]

This parameter declares the token to be rolled out as a rollout token and restricts its use to the self-service portal. Corresponds to the alternative notation:


scope [optional]

This parameter defines the exact validity of the token.

scope={"path":["userservice", "validate"]}

Login to the self-service portal and other portals is allowed for this token. You need a policy in scope=authentication with action=rollout_token_allow_validate for control.

A valid session cookie is required - not every body should be able to enroll tokens ;)


Details about using LinOTP's API (like session handling) can be found here:

This is what LinOTP returns for a static password token roll out:

  "detail": {
     "serial": "KIPW00014B53",
     "otpkey": {
        "img": "<img id=\"challenge_qrcode\"    width=200   src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASIAAAEiAQAAAAB1xeIbAAABjElEQVR4nO2YQW6kMBBFX42RWBppDjBHMVfLkeYGcJQ5QCS8d+tnga3QncVkERpElxeArCf5qyiKX2Xi/2v+9Q0InHLKKaecOjtldXUAN4PcdsZDdb0ElSRJCzBbh40ESZLuqefrujTV1XseIP0FS8vvAhkMQjlM12tSsWDjU090qq7Zum9QP3niy1It0FFABojvJjJsm66zqr8ENZuZ2QCkf71s5LbanKN1XZpa836b47Gg+53zqr8CZWOu/l5vw6e/7+6p5+u6NsXq47Wwmvy2HaSJuqfprOovQc1DkN6sg7QEkZabQfTealdqk/eaYgFiAQibb8Hzfh9qLelWPWYvyL0sTTcTsXQ6StfrUC3H71va3HvN2ZNiOzJrlUZTlGrl95qzG1VjX+eYLdhSgbS0v4HHflcqt1n9bGbMQxAQvObsSX0dnMX3zqArmv+0EfJp1V+Nyn3192k5la7rUY/1vpp86pPX+x2pR5+zdrNJhfVVeOz3ox7nmKqXoNbhHqPLKaeccsqpn6U+ABBc4uZoiArkAAAAAElFTkSuQmCC\"/>",
        "order": "1",
        "value": "seed://123456",
        "description": "OTP Seed"
  "version": "LinOTP 2.12.2",
  "jsonrpc": "2.0802",
  "result": {
     "status": true,
     "value": true
  "id": 1

Now the token can be found in the token management GUI:

In the token info you can find the allowed usage range of the new token.

The validity of a rollout token can be set like any other token.

https://LINOTP/admin/set?session=COOKIE&serial=KIPW000102AF& \
  countAuthSuccessMax=3& \
  countAuthMax=5& \
  validityPeriodStart=18/12/2020%2017:17& \


Transfer the password (or the QR code in case of a OATH soft token) to the user over a secure channel.

The rollout procedure of the User Token

Let's take care of the self service first

The self service portal should be protected with 2FA.

This can be achieved by this policy:

The user access the self service portal: https://LINOTP:

The static password is entered in the OTP field. In case of e.g. an OATH token the OTP must be provided.

Now the user is logged in and can enroll the actual token:

At first he does not see any token on the left side, because the rollout token is invisible for him. The first token is rolled out here with step 2.

The user possesses two tokens now:

The rollout token is now no longer necessary and can be deleted.

Remove unrequired rollout token automatically

By default the rollout token stays until actively delete. For security reasons it might be sensible to remove the rollout token once the user has the final token. This can be configured via the following policy:

This policy will delete the rollout token automatically after the user has successfully authenticated with another token. So this is useful to clean up unnecessary (because successfully used) rollout token.

Please mind - the rollout token is not directly deleted after the rollout of a new token. It is removed after the first successful usage of the self enrolled personal token of the User. This is to mitigate problems during the rollout process of the personal token, e.g. if the user forgets to scan the QR code. Because the rollout token is still active the user can try the rollout again. So the user has to prove a successful rollout via authentication with the new personal token, before the rollout token is purged. This authentication can happen either at the self service portal itself or any other way of authentication.

A test login with https://LINOTP/auth/index or directly in self service is sufficient to delete the rollout token.

If the self service portal is only accessible via a VPN or equivalent.

The rollout token was rolled out with scope={"path":["userservice", "validate"]}. Now we define the access via validate.

The two policies in scope=authorization with action="authorize, tokentype=PW" allow validation for tokens of this type. The client contains the accesses through which the login is possible. For this, "Override authentication client:" must be set to ', ::1' in the system configuration. If this policy is not set, validation is possible from all clients.