Change Pin On First Use Not Working


I have setup a TOTP token and set a default PIN for the token. I also have an enrollment policy setup to require change_pin_on_first_use.

When I login using this PIN via SAML or RADIUS, I have confirmed that the code branch in check_token_list in hits the below code block, but I am not sent a challenge to change my PIN.

if len(valid_token_list) == 1:
    # If only one token was found, we add the serial number,
    # the token type and the OTP length
    reply_dict["serial"] = valid_token_list[0].token.serial
    reply_dict["type"] = valid_token_list[0].token.tokentype
    reply_dict["otplen"] = valid_token_list[0].token.otplen
    # If exist, add next pin and next password change
    next_pin = valid_token_list[0].get_tokeninfo("next_pin_change")
    if next_pin:
        reply_dict["next_pin_change"] = next_pin
        reply_dict["pin_change"] = valid_token_list[0].is_pin_change()
    next_passw = valid_token_list[0].get_tokeninfo("next_password_change")
    if next_passw:
        reply_dict["next_password_change"] = next_passw
        reply_dict["password_change"] = valid_token_list[0].is_pin_change(password=True)
        reply_dict["message"] = ", ".join(message_list)


This is only an information for the client to request the user to change the pin.


So this is not implemented in the way that RSA does it then? In RSA SecurID Authentication Manager, the administrator sets a default PIN. Once the user first authenticates, they receive a challenge to setup a new PIN. This functionality is critical for us to migrate to this system and still pass client/regulatory audits.


Yes, it is not implemented this way.
This is no RSA drop-in.


Would you be against adding this as a feature to the master branch if I wrote it?


I see what you mean about it just being a message. I’m looking into modifying the RADIUS plugin and SAML plugin to handle the PIN challenge there.


The thing is, that RSA designed this PIN setting mechanism several years ago.
This mechanism is old. And in my opinion it is clumsy. And it is mostly tied to RADIUS.

So my personal ambition to add such a functionality is rather…

There are a lot of setup with a couple thousands of users and there are a lot of possibilities to distribute tokens to users and to have users set their OTP PIN (if they are using an OTP PIN at all) in a more modern manner with nice interfaces and a nicer user story.

We always try to not add “Feature X” to privacyIDEA. We might end up with a cluttered interface were you can choose to activate hundrets of specific features.

Of course you are welcome to add this functionality, with probably the following requirements:

  1. try to implement a functionality that is somehow generic and not to much bound to a specific feature. THis is usually achieved by before implementing something, start a discussion about it and thus…
  2. …open an issue at github for it.
  3. Do not clutter the code
  4. Do not clutter the UI


  1. Use documentation and comments in your code.
  2. Add documentation in the doc/ directory
  3. Add unittest, which would probably mean to add a mock for this.

These points would be covered during the way of the review of the pull request.
So no, basically we are not against adding new functionality.


Do you believe that my current pursuit of modifying the freeRADIUS module to perform the pin change logic instead of modifying privacyIDEA is the way to go?


I personally would not do this.
As you might understand I would choose a totally other workflow.

The pin-change-require in the response was added with the idea, that a web application could use this information to display a decent dialog “Dear user, please change your PIN…”.
I really do not like doing this in the RADIUS protocol.
I think there are a lot of other ways, and imho better ways to do this.

But if you really want to and need to go for it, changing the RADIUS plugin has the lower impact on the privacyIDEA code. I.e. you could fork the radius plugin and still use the originial privacyIDEA server code. Changing the plugin you fork a much smaller code base, which makes maintaining and updating a lot easier!


I totally agree that a web page would be much nicer for the user and more robust in nature. Unfortunately we won’t be able to utilize a web application for our integration since we’ll be integrating things like Pulse Secure and VMware Horizon View which only have tie-ins via RADIUS or sometimes SAML.

Some of the users that will be utilizing the 2FA will have no access to our internal network so any PIN resets/setups would have to be done over RADIUS or SAML. We would like to avoid putting a self-service page for 2FA on the public internet.


Yes, you should not put the selfservice on the internet. But there are still other ways to enroll tokens and PINs to users, by granting them first access to the intranet and thus to the selfservice portal to be able to enroll their tokens and PINs.
But anyhow, if you want to stick with your current scenario, go for it! Just to make you understand, why in our world this feature is not really needed deperately.


So I ran into something that I’m not sure how to work with. I have both my RADIUS and SAML applications updated to check for the change_pin flag in the result message. They then ask the user to create a new PIN and confirm it. But at this point I now need to send a token/setpin to the API which either 1) requires an administrative user or 2) requires me to be logged in as the user themselves.

If I use an administrative user to set the PIN, the next_change_date gets reset to the current time and the user gets prompted to change their PIN again the next time they authenticate. And I am unable to impersonate or login as the user in question since I will not be receiving their LDAP password (and I would prefer not to fake a login in the first place)

Is there a way to update a token’s PIN during a validation or a way to change the PIN without it being an administrative change? For example passing the token serial, current PIN, and new PIN?


I ended up using the /auth instead of /validate/check in order to receive the authorization token in order to properly call the /token/setpin as the user authenticating.

My crazy commit is here:


Interesting! Add a new dependency to memcached, for saving transaction between requests!