Serial key for token/init POST: character restrictions problem

Ladies and Gentlemen,

we can successfully use the REST interface to generate OTP tokens and assign them to specific users. However, FreeOTP (a mobile app for generating OTP codes; this is possibly also true for other such apps) apparently does not use the issuer key in the QR encoded URL but looks for the older format and Google Key Uri Format · google/google-authenticator Wiki · GitHub also recommends using the issuer key in addition to providing the issuer in the label.

But this requires a serial key containing at least a “:” - trying this (or “%3a”) the REST interface returns:

ERR905: Invalid serial number. Must comply to ^[0-9a-zA-Z\\-_]+$.

Is there a way to create the recommended QR code using the REST interface (the GUI generated QR codes also seem to have this problem when using an enrollment policy with a tokenlabel containing “:”)?

We could, of course, “roll our own” and create a different QR code (using the Python qrcode package, or similar) - it just seems unsatisfactory as the base64-encoded image returned by the REST call is almost exactly what we need.

Many thanks in advance!

We now use a workaround by creating our own QR code and only using the URL generated by privacyidea.

Here is a Python3 snippet:

js was returned by the REST interface,
img_modified is the base64 encoded image
issuer is what we want to have displayed in the smartphone app

it requires the qrcode · PyPI package

import base64
from io import BytesIO
import qrcode
...
    url_orig = js["detail"]["googleurl"]["value"]
    url = url_orig.replace("//totp/", f"//totp/{issuer}:")
    qr = qrcode.QRCode(
        version=1,
        box_size=10,
        border=5)
    qr.add_data(url)
    qr.make(fit=True)
    img = qr.make_image(fill='black', back_color='white')
    buffered = BytesIO()
    img.save(buffered, format="PNG")
    b64 = base64.b64encode(buffered.getvalue()).decode("utf-8")
    img_modified = ("data:image/png;base64," + b64)

This was helpful: Is it possible to create a QR Code for an image using the python-qrcode library? - Stack Overflow

Have you considered setting the tokenissuer and the tokenlabel via the corresponding policies?
https://privacyidea.readthedocs.io/en/latest/policies/enrollment.html#tokenissuer

You must not use the privacyIDEA serial number to mess with display values in any authenticator app.

As mentioned above, we are already using a policy where we set tokenissuer and tokenlabel. We can see that the issuer entry is actually being used in the URLs returned by the REST interface (also when doing this via the WebGui) - but only in the new format (issuer=Example) and not as part of the label (separated by a colon) as recommended by Google.

Our workaround seems to solve this problem which otherwise results in irritating messages by FreeOTP.

Thanks for noting! We will look into this.

Well, using the issuer parameter is not only “recommended” but “strongly recommended”.

Did you also file a request with FreeOTP?

Otherwise use the best authenticator app on the market :slight_smile:

However, if you have a static token issuer, you can define a tokenlabel policy like:

 YourTokenIssuer:<s>

Which will have your expected outcome.