OTPme Step-by-Step Guide

Learn how to use OTPme step by step.

  • make sure you have read the INSTALL file and have installed OTPme successful.

Lets start with an simple setup with just two users without any group or client.

For this we have to set "ALLOW_GROUP_MISSING="True" in "/etc/otpme/otpme.conf".

That's needed because by default OTPme does not allow a user to be authenticated without using an access group.

This is a security consideration because its more secure to use access groups and restrict token usage only to specific applications.

But for the beginning of this guide we will use the less secure setup....

First you may want to check that there is no existing user.

# otpme-user show
user name           status   sessions  fails  max  description
----------------------------------------------------------------------

That's how it should look for new installation.

No we can add the first user.

# otpme-user add testuser1

And check that it was added successful.

# otpme-user show
user name           status   sessions  fails  max  description
----------------------------------------------------------------------
testuser1            Enabled  Disabled    0     5

It's also possible to show the user details.

# otpme-user show testuser1
user info:
        status:           active (0 failed logins)
        sessions:      Disabled
        max_fail:        5
        description:

user tokens:
        token name      token type    status    access groups      description
        ----------------------------------------------------------------------------------

As you can see the user does not have any token by default. Without a token every authentication request will fail (e.g. the user cannot login to anything)

Let's check this.

# otpme-auth verify testuser1 somepass
Reject

You may want to enable debbuging to see what happens in detail.

# otpme-auth -d verify testuser1 somepass
DEBUG: Processing clear-text authentication request.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: NOTICE: ALLOW_GROUP_MISSING is configured. Getting a list of all user tokens.
WARNING: Unable to find a token to verify this request.
DEBUG: Counting failed login for this request.
WARNING: AUTH_TOKEN_MISSING: user=testuser1 token= access_group= client= client_ip= auth_type=clear-text session=
Reject

As you can see authentication fails with "AUTH_TOKEN_MISSING:". That's how it should be for a user without a token.

If you show the user info again you'll see that there was a failed login counted for this user.

# otpme-user show testuser1
user info:
        status:           active (1 failed logins)
        sessions:      Disabled
        max_fail:        5
        description:

user tokens:
        token name      token type    status    access groups      description
        ----------------------------------------------------------------------------------

You may ask why there is just one failed login because we tried it two times (without and with debbung enabled).
The reason is that OTPme counts only one login failure per used password and as we used the same password for both commands just one is counted.
This feature is useful because for example an wrong configured mail client which tries to login with the same password again and again will probably not lock the user account.

If you try again with a different password failed logins will increase.

# otpme-auth verify testuser1 `echo $RANDOM`
Reject
# otpme-auth verify testuser1 `echo $RANDOM`
Reject
# otpme-auth verify testuser1 `echo $RANDOM`
Reject
# otpme-auth verify testuser1 `echo $RANDOM`
Reject
# otpme-auth verify testuser1 `echo $RANDOM`
Reject
# otpme-auth verify testuser1 `echo $RANDOM`
Reject

Lets see what happens.

# otpme-user show testuser1
user info:
        status:           locked!!! (7 failed logins)
        sessions:      Disabled
        max_fail:        5
        description:

user tokens:
        token name      token type    status    access groups      description
        ----------------------------------------------------------------------------------

Now the complete user account is locked because max_fail is set to "5". You will see later that in a more complex setup with access groups, a user will only be locked for the used group and not the whole account.

So let's add an token to the user account. The following command will add a "static-password-token" with the name "notebook" to the user.

# otpme-token add testuser1/notebook password
Token password: yahxoqueethequiw

# otpme-user show testuser1
user info:
        status:           locked!!! (7 failed logins)
        sessions:      Disabled
        max_fail:        5
        description:

user tokens:
        token name      token type    status    access groups      description
        ---------------------------------------------------------------------------------
        notebook         password      Enabled

Now the user can use a static password to be authenticated. The token password was printed to screen on token creation.
You should note the password (e.g. in a secure password manager) because it is not saved anywhere in clear-text.
If you loose the password you have to set a new one for this token with the command: otpme-token password testuser1/notebook [newpass]

But for now we keep the generated password and try to authenticate the user.

# otpme-auth verify testuser1 yahxoqueethequiw
Reject

That hasn't worked. Lets try with debugging enabled.

# otpme-auth -d verify testuser1 yahxoqueethequiw
DEBUG: Processing clear-text authentication request.
WARNING: User 'testuser1' is locked.
WARNING: AUTH_USER_LOCKED: user=testuser1 token= access_group= client= client_ip= auth_type=clear-text session=
Reject

Uuups. The account is still locked. :)

Let's unlock.

# otpme-user unlock testuser1

# otpme-user show testuser1
user info:
        status:           active (0 failed logins)
        sessions:      Disabled
        max_fail:        5
        description:

user tokens:
        token name      token type    status    access groups      description
        ----------------------------------------------------------------------------------
        notebook         password      Enabled

Okay. Account unlocked and "failed logins" reset to "0".

Let's try again to authenticate.

# otpme-auth -d verify testuser1 yahxoqueethequiw
DEBUG: Processing clear-text authentication request.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: NOTICE: ALLOW_GROUP_MISSING is configured. Getting a list of all user tokens.
DEBUG: Will try the following static password tokens to verify this request: notebook
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'notebook'.
DEBUG: Token 'notebook' verified successful.
INFO: Resetting login fail count for 'testuser1' from '1' to '0'.
INFO: AUTH_OK_STATIC: user=testuser1 token=notebook access_group= client= client_ip= auth_type=clear-text session=
Accept

Great! You got your first working OTPme setup. :)

Now you should add the second user with the name "testuser2" and add a static-password-token with the name "tablet" to the user.
After this you should check that authentication works for the second user.

Your setup should look like this now.

# otpme-user show
user name          status    sessions  fails  max  description
----------------------------------------------------------------------
testuser1           Enabled  Disabled    0     5
testuser2           Enabled  Disabled    0     5

# otpme-user show testuser1
user info:
        status:           active (0 failed logins)
        sessions:      Disabled
        max_fail:        5
        description:

user tokens:
        token name      token type    status    access groups      description
        ----------------------------------------------------------------------------------
        notebook         password      Enabled

# otpme-user show testuser2
user info:
        status:          active (0 failed logins)
        sessions:      Disabled
        max_fail:       5
        description:

user tokens:
        token name      token type    status    access groups      description
        ----------------------------------------------------------------------------------
        tablet                password      Enabled

Now let's add another token to both users.

# otpme-token add testuser1/mobile-otp motp
# otpme-token add testuser1/mobile-otp motp

# otpme-user show testuser1
user info:
        status:           active (0 failed logins)
        sessions:      Disabled
        max_fail:        5
        description:

user tokens:
        token name      token type    status    access groups      description
        ----------------------------------------------------------------------------------
        mobile-otp         motp              Enabled
        notebook          password      Enabled

This time we added an motp token. This is a OTP token which can be used to create a One-Time-Password that get's invalid after it was used.
You can get more infos on motp and where to get a softtoken for your device at: http://motp.sourceforge.net/

But for this guide there is no need to get a softtoken as you can generate OTPs for testing with otpme-token.

Let's try it.

# otpme-token gen testuser1/mobile-otp
eaba7e

# otpme-auth -d verify testuser1 eaba7e
DEBUG: Processing clear-text authentication request.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: NOTICE: ALLOW_GROUP_MISSING is configured. Getting a list of all user tokens.
DEBUG: Will try the following static password tokens to verify this request: notebook
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'notebook'.
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group= client= client_ip= auth_type=clear-text session=new:d7fa39cc7a36f52da12229973747d307
Accept

Works as expected. :)

If you try again authentication fails because the OTP was already used.

# otpme-auth -d verify testuser1 eaba7e
DEBUG: Processing clear-text authentication request.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: NOTICE: ALLOW_GROUP_MISSING is configured. Getting a list of all user tokens.
DEBUG: Will try the following static password tokens to verify this request: notebook
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'notebook'.
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
WARNING: OTP from this request was already used. Authentication will fail.
DEBUG: Counting failed login for this request.
WARNING: AUTH_OTP_ALREADY_USED: user=testuser1 token=mobile-otp access_group= client= client_ip= auth_type=clear-text session=
Reject

That's how its intended with One-Time-Passwords. :)
But there may be situations where it's needed to make re-use of an otp possible.

For this you have to enable "OTP-Sessions" for the user:

# otpme-user enable_sessions testuser1

Now we can re-use an OTP until the session expires (see SESSION_TIMEOUT and UNUSED_SESSION_TIMEOUT in /etc/otpme/otpme.conf).

# otpme-token gen testuser1/mobile-otp
6c305c

# otpme-auth -d verify testuser1 6c305c
DEBUG: Processing clear-text authentication request.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: NOTICE: ALLOW_GROUP_MISSING is configured. Getting a list of all user tokens.
DEBUG: Will try the following static password tokens to verify this request: notebook
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'notebook'.
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
INFO: Resetting login fail count for 'testuser1' from '1' to '0'.
DEBUG: Creating session 'testuser1:clear-text:ac210cfcf084080b2fbdbfc5ab676618'.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group= client= client_ip= auth_type=clear-text session=new:ac210cfcf084080b2fbdbfc5ab676618
Accept

# otpme-auth -d verify testuser1 6c305c
DEBUG: Processing clear-text authentication request.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:clear-text:ac210cfcf084080b2fbdbfc5ab676618'.
DEBUG: Authentication parameters of request matching session 'testuser1:clear-text:ac210cfcf084080b2fbdbfc5ab676618'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Session token 'mobile-otp' is owned by user 'testuser1'. Session valid.
DEBUG: Updating last used timestamp of session 'testuser1:clear-text:ac210cfcf084080b2fbdbfc5ab676618'.
INFO: AUTH_OK_SESSION: user=testuser1 token=mobile-otp access_group= client= client_ip= auth_type=clear-text session=ac210cfcf084080b2fbdbfc5ab676618
Accept

At this stage we have a setup where we could use the static-password-token for e.g. wlan authentication and the otp-token for e.g. webmail login over the internet.
But we have the problem that both tokens could be used for both "applications", wlan and webmail. That's where access groups and clients come into play.

A client in OTPme is what a NAS-Identifier is for radius. You can think of it as a "name" for "applications" that send authentication requests to OTPme.

The requests that the "application" wlan sends comes from the wlan access-points. In our example we assume that we use linksys APs.

So we add an client for one AP.

# otpme-client add linksys1

# otpme-client show
client name         status     tp_check  access group    addresses       description
------------------------------------------------------------------------------------------------
linksys1              Enabled  Disabled

We could add ip addresses to this client to make sure only requests from the configured ip addresses get processed by OTPme.
But for now we keep the setup simple and allow requests from any ip.

The "thing" that brings together clients and user/tokens is a access group.

So we add an access group for wlan authentication.

# otpme-group add wlan

# otpme-group show
group name      status        child groups    max_fail  (sessions    child sessions   master  max_login timeout utimeout description)
-----------------------------------------------------------------------------------------------------------------------------------------------------------
wlan                  Enabled                                   5         Disabled                               False          0            30         5

The next step is to configure the access group for our first client "linksys1" and assign the access group to the user tokens.

Configure client access group.

# otpme-client access_group linksys1 wlan

# otpme-client show
client name         status       tp_check  access group    addresses       description
--------------------------------------------------------------------------------------------------
linksys1              Enabled    Disabled   wlan

Add access group to user token.

# otpme-token add_group testuser1/notebook wlan

# otpme-user show testuser1
user info:
        status:           active (0 failed logins)
        sessions:      Enabled
        max_fail:        5
        description:

user tokens:
        token name      token type    status     access groups      description
        ----------------------------------------------------------------------------------
        mobile-otp         motp             Enabled
        notebook          password     Enabled   wlan

You should do the same for testuser2.

Now let's add a client and group for webmail access and assign it to the user tokens.

# otpme-client add roundcube
# otpme-group add webmail
# otpme-client access_group roundcube webmail
# otpme-token add_group testuser1/mobile-otp webmail
# otpme-token add_group testuser2/mobile-otp webmail

We use roundcube as webmail in our example so we name the client roundcube.
There is nothing that speak against using the same name for the client and the access group but i prefer to use different names.

At this point we should verify that only the configured tokens can be used to authenticate a user for the "application" (access group).

# otpme-auth -d verify testuser1 yahxoqueethequiw linksys1
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'linksys1' exists.
DEBUG: Got access group 'wlan' from client config.
DEBUG: Session creation for access group  'wlan' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'wlan'.
DEBUG: Selecting token 'notebook' based on access group 'wlan'.
DEBUG: Will try the following static password tokens to verify this request: notebook
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'notebook'.
DEBUG: Token 'notebook' verified successful.
INFO: AUTH_OK_STATIC: user=testuser1 token=notebook access_group=wlan client=linksys1 client_ip= auth_type=clear-text session=
Accept

# otpme-auth -d verify testuser1 yahxoqueethequiw roundcube
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Session creation for access group  'webmail' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Counting failed login for this request.
WARNING: AUTH_FAILED: user=testuser1 token= access_group=webmail client=roundcube client_ip= auth_type=clear-text session=
Reject

# otpme-token gen testuser1/mobile-otp
e25f5a

# otpme-auth -d verify testuser1 e25f5a roundcube
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Session creation for access group  'webmail' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
INFO: Resetting login fail count for 'testuser1/webmail' from '1' to '0'.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=webmail client=roundcube client_ip= auth_type=clear-text session=new:9eeb0e48c53981db687260f0111f75f0
Accept

# otpme-token gen testuser1/mobile-otp
b1d922

# otpme-auth -d verify testuser1 b1d922 linksys1
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'linksys1' exists.
DEBUG: Got access group 'wlan' from client config.
DEBUG: Session creation for access group  'wlan' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'wlan'.
DEBUG: Selecting token 'notebook' based on access group 'wlan'.
DEBUG: Will try the following static password tokens to verify this request: notebook
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'notebook'.
DEBUG: Verifying otp tokens...
DEBUG: Counting failed login for this request.
WARNING: AUTH_FAILED: user=testuser1 token= access_group=wlan client=linksys1 client_ip= auth_type=clear-text session=
Reject

Yeah! Works great! ;)
It should be the same for testuser2 If you've done everything right.

You can see that we have restricted the use of user tokens to specific "applications".
This way you can choose strong passwords for you wlan clients (notebooks, tables, mobiles etc.) which can only be used for wlan authentication
and you can use secure OTPs for webmail access from the internet. If a device gets stolen or lost you can easily change the token password
and everything is fine. No need to change the wlan login credentials of other devices. Also no need to change any other credentials of the user as
you can add a token for each wlan device the user owns.

But let's continue with the webmail config which is still not ready to be used with roundcube.
The reason is that roundcube just passes the passsword (otp) you use at the login page to the imap server which will verify it against OTPme.
And this verification is done not only once. Normally a request is send for each access to the mailbox (e.g. if you click on a mail).

So we need to enable sessions for the group webmail.

# otpme-group enable_sessions webmail

You may ask why we have to enable sessions for the group if we have still enabled sessions for the user.
That's because groups do not inherit this setting from the user which is a design decision.

Talking about this is a good time to disable sessions again for the user and also disable ALLOW_GROUP_MISSING in /etc/otpme/otpme.conf as using a setup without groups is for pussies. ;)

# otpme-user disable_sessions testuser1

Okay, we enabled sessions for the group webmail which will allow the imap server to re-use the webmail password (otp) until the session expires.

So let's have a look to the session tool.

First we need to authenticate the user with the webmail access group to get a session created.

# otpme-token gen testuser1/mobile-otp
d1f9c1

# otpme-auth -d verify testuser1 d1f9c1 roundcube
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
DEBUG: adding parent session 'testuser1:webmail:clear-text:05f6ac9c243faf17d92e82c615c7dec4'
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=webmail client=roundcube client_ip= auth_type=clear-text session=new:05f6ac9c243faf17d92e82c615c7dec4
Accept

As you can see a session gets created. Every following request for this group with the same password will be accepted until the session expires.

# otpme-auth -d verify testuser1 d1f9c1 roundcube
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:webmail:clear-text:05f6ac9c243faf17d92e82c615c7dec4'.
DEBUG: Authentication parameters of request matching session 'testuser1:webmail:clear-text:05f6ac9c243faf17d92e82c615c7dec4'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'webmail' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'webmail' is in token access groups and enabled, so its valid.
DEBUG: Session token 'mobile-otp' is owned by user 'testuser1'. Session valid.
DEBUG: Updating last used timestamp of session 'testuser1:webmail:clear-text:05f6ac9c243faf17d92e82c615c7dec4'.
INFO: AUTH_OK_SESSION: user=testuser1 token=mobile-otp access_group=webmail client=roundcube client_ip= auth_type=clear-text session=05f6ac9c243faf17d92e82c615c7dec4
Accept

Now it's time to check the session details. :)

# otpme-session show
session id                                                user             token           type          access group     client            client_ip       last login    expire      unused exp.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
05f6ac9c243faf17d92e82c615c7dec4  testuser1       mobile-otp   clear-text   webmail              roundcube                       17:33:10    17:59:34  17:38:10

In the session list you can see the last login time and the expiry times for the session.
Have a look at config file for default values and an description of both timeout settings.

A good idea is to configure the timeout values per group depending on you the application requirements.

So you may want to set the session-timeout to 10 hours which is basically a "destroy session after 10 hours".
And you may want to set the unused-session-timeout to 1 hour which destroys the session after being unused for an hour.

# otpme-group timeout webmail 600
# otpme-group unused_timeout webmail 60

But timeout settings always depends on different factors. If you for example want to use OTPs for wlan login you may want to set both timeouts
to a day (1440 minutes) because you want a guest to be "logged out" from wlan after a day.

Okay, back to our webmail group. We named the client roundcube as we use roundcube as webmail in our scenario.
But as said before technically the request will come from the imap server (e.g. cyrus-imap).

So lets rename the client to cyrus-imap.

# otpme-client rename roundcube cyrus-imap

# otpme-client show
client name         status       tp_check  access group    addresses       description
--------------------------------------------------------------------------------------------------
cyrus-imap         Enabled    Disabled   webmail
linksys1              Enabled    Disabled   wlan

That's all you need to do to rename. Group membership etc. is all kept.

With this setup you could use roundcube as you webmail for receiving and sending of mails as long as the used MTA (e.g. postfix) is NOT configured to do smtp authentication.

If you want to use smtp authentication you have to ensure that OTPme will allow access to requests coming from postfix.

So let's check how to implement this with OTPme.

First we need to add a client to handle requests that comes from postfix.

# otpme-client add postfix

Then we need to configure the group for this client.

# otpme-client access_group postfix webmail

That's it. Let's try authentication for both clients.

# otpme-token gen testuser1/mobile-otp
a1bf23

# otpme-auth -d verify testuser1 a1bf23 cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
DEBUG: adding parent session 'testuser1:webmail:clear-text:ea1e658bf4c350446033cef1b7b0f447'
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=webmail client=cyrus-imap client_ip= auth_type=clear-text session=new:ea1e658bf4c350446033cef1b7b0f447
Accept

# otpme-auth -d verify testuser1 a1bf23 postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:webmail:clear-text:ea1e658bf4c350446033cef1b7b0f447'.
DEBUG: Authentication parameters of request matching session 'testuser1:webmail:clear-text:ea1e658bf4c350446033cef1b7b0f447'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'webmail' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'webmail' is in token access groups and enabled, so its valid.
DEBUG: Session token 'mobile-otp' is owned by user 'testuser1'. Session valid.
DEBUG: Updating last used timestamp of session 'testuser1:webmail:clear-text:ea1e658bf4c350446033cef1b7b0f447'.
INFO: AUTH_OK_SESSION: user=testuser1 token=mobile-otp access_group=webmail client=postfix client_ip= auth_type=clear-text session=ea1e658bf4c350446033cef1b7b0f447
Accept

Okay, works as it should.

But what if we need to allow imap only access for a user (e.g. a user that reads spam mails from an imap folder to feed spamassassin)?
We dont need and want access to mail sending via postfix for this user! That's where child sessions come into play.

First we need to add a group for each client.

# otpme-group add smtp
# otpme-group add imap
# otpme-client access_group postfix smtp
# otpme-client access_group cyrus-imap imap

Now we can delete the webmail group as its not need anymore.

# otpme-group del webmail
Group 'webmail' is used by this tokens: testuser1/mobile-otp, testuser2/mobile-otp
Delete group webmail?: y

As you can see OTPme asks you before deleting objects that a referenced by others. :)

Now we need to make sure a child session for smtp (postfix) is created if a user logges into imap.

# otpme-group add_child_session imap smtp
# otpme-group enable_sessions imap

# otpme-group show
group name      status      child groups    max_fail  (sessions   child sessions   master  max_login timeout utimeout description)
------------------------------------------------------------------------------------------------------------------------------------------------------
imap                  Enabled                                5          Enabled     smtp                  False          0           30           5
smtp                  Enabled                                5          Disabled                             False          0           30           5
wlan                  Enabled                                5          Disabled                              False          0           30           5

Let's try it.

# otpme-token gen testuser1/mobile-otp
484af2

# otpme-auth -d verify testuser1 484af2 cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'imap'.
WARNING: Unable to find a token to verify this request.
DEBUG: Counting failed login for this request.
WARNING: AUTH_TOKEN_MISSING: user=testuser1 token= access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=
Reject

Yeah, we forgot to add the imap group to the user tokens.

# otpme-token add_group testuser1/mobile-otp imap
# otpme-token add_group testuser2/mobile-otp imap

# otpme-auth -d verify testuser1 484af2 cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'imap'.
DEBUG: Selecting token 'mobile-otp' based on access group 'imap'.
DEBUG: Selecting token 'mobile-otp' based on access group 'imap'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
INFO: Resetting login fail count for 'testuser1/imap' from '1' to '0'.
DEBUG: adding parent session 'testuser1:imap:clear-text:6633037dff96c241dd76dfd447ebe46a'
DEBUG: adding child session 'testuser1:smtp:clear-text:1ecd0b333c64aa63822f71916799526a'.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=new:6633037dff96c241dd76dfd447ebe46a
Accept

Better :)

# otpme-auth -d verify testuser1 484af2 postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'smtp' from client config.
DEBUG: Session creation for access group  'smtp' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:smtp:clear-text:1ecd0b333c64aa63822f71916799526a'.
DEBUG: Authentication parameters of request matching session 'testuser1:smtp:clear-text:1ecd0b333c64aa63822f71916799526a'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'smtp' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'smtp' is NOT in token access groups. Verifying parent groups.
WARNING: Session verification failed because access group 'smtp' and none of its parents are in token access groups (and enabled).
DEBUG: Counting failed login for this request.
WARNING: AUTH_SESSION_NO_VALID_GROUP: user=testuser1 token= access_group=smtp client=postfix client_ip= auth_type=clear-text session=
Reject

But postfix does still not work because the group "smtp" is not assigned to the user tokens.

We could add the group to the token now and it would work. But its nicer to use child groups for this.

# otpme-group add_child_group imap smtp

# otpme-group show
group name      status    child groups    max_fail  (sessions   child sessions   master  max_login timeout utimeout description)
-----------------------------------------------------------------------------------------------------------------------------------------------------
imap                 Enabled   smtp                     5        Enabled      smtp                 False            0          30           5
smtp                 Enabled                               5         Disabled                             False            0          30           5
wlan                 Enabled                               5         Disabled                             False            0          30           5

This way the child group "smtp" inherits the token permissions from the parent group "imap".

# otpme-auth -d verify testuser1 484af2 postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'smtp' from client config.
DEBUG: Session creation for access group  'smtp' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:smtp:clear-text:1ecd0b333c64aa63822f71916799526a'.
DEBUG: Authentication parameters of request matching session 'testuser1:smtp:clear-text:1ecd0b333c64aa63822f71916799526a'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'smtp' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'smtp' is NOT in token access groups. Verifying parent groups.
DEBUG: Parent group 'imap' IS in token access groups and enbaled, so its valid.
INFO: Found a valid parent access group: 'imap'
DEBUG: Session token 'mobile-otp' is owned by user 'testuser1'. Session valid.
DEBUG: Updating last used timestamp of session 'testuser1:smtp:clear-text:1ecd0b333c64aa63822f71916799526a'.
INFO: Resetting login fail count for 'testuser1/smtp' from '1' to '0'.
INFO: AUTH_OK_SESSION: user=testuser1 token=mobile-otp access_group=smtp client=postfix client_ip= auth_type=clear-text session=1ecd0b333c64aa63822f71916799526a
Accept

You can use this to inherit access permissions from different levels of parent -> child group relations.
An example would be an Web Single-Sign-On portal which should allow access to different web applications. But we will see this later.

At the moment we just want to allow a user called "spam" to fetch mails from an imap folder but dont want the user to allow access to mail sending via smtp (postfix)

We start with adding the user and add a static-password-token to it.

# otpme-user add spam

# otpme-token add spam/imap-pass password
Token password: ieteijefohkeecai

Now let's check what happens if we allow this user/token to access the imap server.

# otpme-token add_group spam/imap-pass imap

# otpme-auth -d verify spam ieteijefohkeecai cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'imap'.
DEBUG: Selecting token 'imap-pass' based on access group 'imap'.
DEBUG: Will try the following static password tokens to verify this request: imap-pass
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'imap-pass'.
DEBUG: Token 'imap-pass' verified successful.
INFO: AUTH_OK_STATIC: user=spam token=imap-pass access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=
Accept

Okay, works....

# otpme-auth -d verify spam ieteijefohkeecai postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'smtp' from client config.
DEBUG: Session creation for access group  'smtp' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'smtp'.
DEBUG: Selecting token 'imap-pass' based on parent access group 'imap'.
DEBUG: Will try the following static password tokens to verify this request: imap-pass
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'imap-pass'.
DEBUG: Token 'imap-pass' verified successful.
INFO: AUTH_OK_STATIC: user=spam token=imap-pass access_group=smtp client=postfix client_ip= auth_type=clear-text session=
Accept

But it also works for postfix which is not what we want.

So here's how it could be done.

We re-add the webmail group and give it the child groups "imap" and "smtp" to allow tokens that have access to group "webmail" also access to "imap" and "smtp".

# otpme-group add webmail
# otpme-group add_child_group webmail imap
# otpme-group add_child_group webmail smtp

We remove the child group "smtp" from group "imap" as we dont want smtp access for every imap user, in our case the user "spam".

# otpme-group remove_child_group imap smtp

And we add permission to access webmail group and its parents for the user tokens.

# otpme-token add_group testuser1/mobile-otp webmail
# otpme-token add_group testuser2/mobile-otp webmail

The access permission to group "imap" is not needed anymore.

# otpme-token remove_group testuser1/mobile-otp imap
# otpme-token remove_group testuser2/mobile-otp imap

Let's check if it works...

# otpme-token gen testuser1/mobile-otp
7be894

# otpme-auth -d verify testuser1 7be894 cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: Session 'testuser1:imap:clear-text:6633037dff96c241dd76dfd447ebe46a' is expired by unused session timeout. Removing...
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'imap'.
DEBUG: Selecting token 'mobile-otp' based on parent access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
DEBUG: adding parent session 'testuser1:imap:clear-text:bddb56ee5d71eec1e1016bd3e07bed3a'
DEBUG: adding child session 'testuser1:smtp:clear-text:b2412b4c686f60d98fe36d63856ff42f'.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=new:bddb56ee5d71eec1e1016bd3e07bed3a
Accept

# otpme-auth -d verify testuser1 7be894 postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'smtp' from client config.
DEBUG: Session creation for access group  'smtp' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:smtp:clear-text:b2412b4c686f60d98fe36d63856ff42f'.
DEBUG: Authentication parameters of request matching session 'testuser1:smtp:clear-text:b2412b4c686f60d98fe36d63856ff42f'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'smtp' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'smtp' is NOT in token access groups. Verifying parent groups.
DEBUG: Parent group 'webmail' IS in token access groups and enbaled, so its valid.
INFO: Found a valid parent access group: 'webmail'
DEBUG: Session token 'mobile-otp' is owned by user 'testuser1'. Session valid.
DEBUG: Updating last used timestamp of session 'testuser1:smtp:clear-text:b2412b4c686f60d98fe36d63856ff42f'.
INFO: AUTH_OK_SESSION: user=testuser1 token=mobile-otp access_group=smtp client=postfix client_ip= auth_type=clear-text session=b2412b4c686f60d98fe36d63856ff42f
Accept

# otpme-auth -d verify spam ieteijefohkeecai cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'imap'.
DEBUG: Selecting token 'imap-pass' based on access group 'imap'.
DEBUG: Will try the following static password tokens to verify this request: imap-pass
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'imap-pass'.
DEBUG: Token 'imap-pass' verified successful.
INFO: AUTH_OK_STATIC: user=spam token=imap-pass access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=
Accept

# otpme-auth -d verify spam ieteijefohkeecai postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'smtp' from client config.
DEBUG: Session creation for access group  'smtp' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'smtp'.
WARNING: Unable to find a token to verify this request.
DEBUG: Counting failed login for this request.
WARNING: AUTH_TOKEN_MISSING: user=spam token= access_group=smtp client=postfix client_ip= auth_type=clear-text session=
Reject

Mission accomplished! ;)

But it's still not perfect as this setup will fail if the first authentication request would come from postfix.

Let's check this.

# otpme-token gen testuser1/mobile-otp
2e6147

# otpme-auth -d verify testuser1 2e6147 postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'smtp' from client config.
DEBUG: Session creation for access group  'smtp' is disabled. Verification of parent sessions will still be done.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:smtp:clear-text:b2412b4c686f60d98fe36d63856ff42f'.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'smtp'.
DEBUG: Selecting token 'mobile-otp' based on parent access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=smtp client=postfix client_ip= auth_type=clear-text session=new:b6ddba6ce72ef2a310d5cc19cc62db2e
Accept

# otpme-auth -d verify testuser1 2e6147 cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:imap:clear-text:bddb56ee5d71eec1e1016bd3e07bed3a'.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'imap'.
DEBUG: Selecting token 'mobile-otp' based on parent access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
WARNING: OTP from this request was already used. Authentication will fail.
DEBUG: Counting failed login for this request.
WARNING: AUTH_OTP_ALREADY_USED: user=testuser1 token=mobile-otp access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=
Reject

That's because the access group "smtp" is a child session of imap but not vice versa.

The first thing that comes into mind is to add "imap" as an child session of "smtp".

It's not a problem to do this and it would work well.

But if you imagine e.g. a big setup for wlan authentication with many access-points where you want to restrict access to different access groups (e.g. different buildings)
it can be very annoying to configure all this parent child relations. That's why there is a feature called "session master".

Let's try it.

First we need to remove group "smtp" as child of "imap".

# otpme-group remove_child imap smtp

Then we need to add both groups as child sessions of group "webmail" and enable sessions for all groups.

# otpme-group add_child_session webmail imap
# otpme-group add_child_session webmail smtp

# otpme-group enable_sessions imap
# otpme-group enable_sessions smtp
# otpme-group enable_sessions webmail

And finally enable session master for group "webmail".

# otpme-group enable_session_master webmail

Now it should look like this.

# otpme-group show
group name      status     child groups    max_fail  (sessions    child sessions  master  max_login timeout utimeout description)
------------------------------------------------------------------------------------------------------------------------------------------------------
imap                 Enabled                                 5         Enabled                              False          0            30            5
smtp                 Enabled                                5         Enabled                               False          0            30            5
webmail            Enabled     imap                    5         Enabled      imap                 True           0            30            5
                                          smtp                                                  smtp
wlan                 Enabled                                5         Disabled                              False          0            30            5

So, lets try it.

# otpme-token gen testuser1/mobile-otp
57b99e

# otpme-auth -d verify testuser1 57b99e postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'smtp' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'smtp'.
DEBUG: Selecting token 'mobile-otp' based on parent access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
DEBUG: Found a valid session master: 'webmail'.
DEBUG: adding parent session 'testuser1:webmail:clear-text:27137c9eaa219d037c6eb99afb947022'
DEBUG: adding child session 'testuser1:imap:clear-text:5da1f344dbfdfe42bc22d120f6a3b788'.
DEBUG: adding child session 'testuser1:smtp:clear-text:20f93b9d04064cbf41fe68ce0c60c7fb'.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=smtp client=postfix client_ip= auth_type=clear-text session=27137c9eaa219d037c6eb99afb947022
Accept

# otpme-auth -d verify testuser1 57b99e cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session'testuser1:imap:clear-text:5da1f344dbfdfe42bc22d120f6a3b788'.
DEBUG: Authentication parameters of request matching session 'testuser1:imap:clear-text:5da1f344dbfdfe42bc22d120f6a3b788'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'imap' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'imap' is NOT in token access groups. Verifying parent groups.
DEBUG: Parent group 'webmail' IS in token access groups and enbaled, so its valid.
INFO: Found a valid parent access group: 'webmail'
DEBUG: Session token 'mobile-otp' is owned by user 'testuser1'. Session valid.
DEBUG: Updating last used timestamp of session 'testuser1:imap:clear-text:5da1f344dbfdfe42bc22d120f6a3b788'.
INFO: Resetting login fail count for 'testuser1/imap' from '3' to '0'.
INFO: AUTH_OK_SESSION: user=testuser1 token=mobile-otp access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=5da1f344dbfdfe42bc22d120f6a3b788
Accept

Okay, looks good. If you would try with a new otp the reverse order (smtp after imap) it would also work.

And last but not least we have to check the spam user access.

# otpme-auth -d verify spam ieteijefohkeecai cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'imap'.
DEBUG: Selecting token 'imap-pass' based on access group 'imap'.
DEBUG: Will try the following static password tokens to verify this request: imap-pass
DEBUG: Verifying static password tokens...
DEBUG: Verifying token 'imap-pass'.
DEBUG: Token 'imap-pass' verified successful.
INFO: AUTH_OK_STATIC: user=spam token=imap-pass access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=
Accept

# otpme-auth -d verify spam ieteijefohkeecai postfix
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'postfix' exists.
DEBUG: Got access group 'smtp' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'smtp'.
WARNING: Unable to find a token to verify this request.
WARNING: AUTH_TOKEN_MISSING: user=spam token= access_group=smtp client=postfix client_ip= auth_type=clear-text session=
Reject

Also works how it should. :)

One important thing you should be aware of is that you cannot use such a setup to add another webmail which uses the same imap
and smtp server and differentiate between both webmail interfaces (e.g. allow user testuser1 to only access webmail1 and testuser2 to access only webmail2).

That's because there is no client webmail1 and webmail2 (or roundcube1 and roundcube2) that sends a request. The request always comes from the client "cyrus-imap".

If you want to make this possible you have to use the roundcube plugin that comes with OTPme.

But the plugin gives you 3 more security improvements.
  1. If you use the plugin you can set "max_login" for the webmail group/session to 1 to prevent that an OTP can be re-used to login to roundcube
  2. The plugin supports the SLP (Session Logout Passord) feature. So your OTP-Session gets destroyed if you logout of roundcube
  3. With the plugin you can use the "Client Trust Password" Feature which protects against keyloggers and uses secure 32-character passwords by default

So let's give it a try. :)

First we have to add client for roundcube because the plugin will send a (radius) request to OTPme at login, just before any other request (e.g. imap).

# otpme-client add roundcube
# otpme-client access_group roundcube webmail

# otpme-client show
client name         status      tp_check  access group    addresses       description
-------------------------------------------------------------------------------------------------
cyrus-imap          Enabled   Disabled     imap
linksys1              Enabled    Disabled    wlan
postfix                 Enabled    Disabled    smtp
roundcube          Enabled    Disabled    webmail

Then we should set max_login for the access group webmail to 1.

# otpme-group max_login webmail 1

Now we can try to login from roundcube.

# otpme-token gen testuser1/mobile-otp
5f0735

# otpme-auth -d verify testuser1 5f0735 roundcube
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
INFO: Resetting login fail count for 'testuser1/webmail' from '1' to '0'.
DEBUG: Found a valid session master: 'webmail'.
DEBUG: adding parent session 'testuser1:webmail:clear-text:c82195200c984ce6c8606b510a652979'
DEBUG: adding child session 'testuser1:imap:clear-text:f73a8a4047b12c24a418b971cd5e3ad6'.
DEBUG: adding child session 'testuser1:smtp:clear-text:0b5efd37000fb985aaf4eee41c0812b6'.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=webmail client=roundcube client_ip= auth_type=clear-text session=new:c82195200c984ce6c8606b510a652979
Accept

A second login should fail...

# otpme-auth -d verify testuser1 5f0735 roundcube
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session 'testuser1:webmail:clear-text:c82195200c984ce6c8606b510a652979'.
DEBUG: Authentication parameters of request matching session 'testuser1:webmail:clear-text:c82195200c984ce6c8606b510a652979'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'webmail' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'webmail' is in token access groups and enabled, so its valid.
WARNING: Session verification failed because max login count (1) is reached.
DEBUG: Counting failed login for this request.
WARNING: AUTH_SESSION_MAX_LOGIN: user=testuser1 token= access_group=webmail client=roundcube client_ip= auth_type=clear-text session=
Reject

...but the client sessions should still work...

# otpme-auth -d verify testuser1 5f0735 cyrus-imap
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'cyrus-imap' exists.
DEBUG: Got access group 'imap' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session 'testuser1:imap:clear-text:f73a8a4047b12c24a418b971cd5e3ad6'.
DEBUG: Authentication parameters of request matching session 'testuser1:imap:clear-text:f73a8a4047b12c24a418b971cd5e3ad6'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'imap' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'imap' is NOT in token access groups. Verifying parent groups.
DEBUG: Parent group 'webmail' IS in token access groups and enabled, so its valid.
INFO: Found a valid parent access group: 'webmail'
DEBUG: Session token 'mobile-otp' is owned by user 'testuser1'. Session valid.
DEBUG: Updating last used timestamp of session 'testuser1:imap:clear-text:f73a8a4047b12c24a418b971cd5e3ad6'.
INFO: AUTH_OK_SESSION: user=testuser1 token=mobile-otp access_group=imap client=cyrus-imap client_ip= auth_type=clear-text session=f73a8a4047b12c24a418b971cd5e3ad6
Accept

So if your setup only allows access to the roundcube webinterface from external and not to imap and smtp you have a real One-Time-Password setup now because you can use an OTP just one time.

We can also try the SLP feature now because the plugin supports it.

# otpme-tool gen_logout 5f0735
2c73d0

# otpme-auth -d verify testuser1 2c73d0 roundcube
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: Verifying session 'testuser1:webmail:clear-text:f1c304808743d21d7423e86a2a0ca33f'.
DEBUG: This is a logout request for session 'testuser1:webmail:clear-text:f1c304808743d21d7423e86a2a0ca33f'.
DEBUG: Token 'mobile-otp' used at session login is a token of user 'testuser1'.
DEBUG: Verifying if access group 'webmail' is in access_groups of token 'mobile-otp'.
DEBUG: Access group 'webmail' is in token access groups and enabled, so its valid.
INFO: Logout request detected. Removing session 'testuser1:webmail:clear-text:f1c304808743d21d7423e86a2a0ca33f'
INFO: AUTH_SESSION_LOGOUT: user=testuser1 token= access_group=webmail client=roundcube client_ip= auth_type=clear-text session=
Reject

Perfect! :)

Now lets check the "Client Trust Password" feature.

We have to add a shared secret to the client roundcube that must be added to the OTPme roundcube plugin config.

# otpme-client secret roundcube
Use auto-generated secret?:
New secret: dbf549610e49f02a

We also need to enable the feature for this client.

# otpme-client enable_tp roundcube

# otpme-client show
client name          status      tp_check   access group    addresses       description
--------------------------------------------------------------------------------------------------
cyrus-imap           Enabled   Disabled    imap
linksys1               Enabled    Disabled    wlan
postfix                  Enabled   Disabled    smtp
roundcube           Enabled    Enabled    webmail

Now we can try it...

# otpme-token gen testuser1/mobile-otp
3a5e9d

# otpme-tool gen_client_tp roundcube 3a5e9d
bef56300a694ce7d0e6828e080952c5e

# otpme-auth -d verify testuser1 bef56300a694ce7d0e6828e080952c5e roundcube
DEBUG: Processing clear-text authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing clear-text session verification.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful a trust password of client 'roundcube'.
DEBUG: Adding OTP from this session to used OTPs of the user.
DEBUG: Found a valid session master: 'webmail'.
DEBUG: adding parent session 'testuser1:webmail:clear-text:971863c1ba69df908bca59aeeca95e52'
DEBUG: adding child session 'testuser1:imap:clear-text:77d739b800b89382c3b30552e1227efa'.
DEBUG: adding child session 'testuser1:smtp:clear-text:27e48e6c037102026862d2a3136fca5a'.
INFO: AUTH_OK_TRUST_PW: user=testuser1 token=mobile-otp access_group=webmail client=roundcube client_ip= auth_type=clear-text session=new:971863c1ba69df908bca59aeeca95e52
Accept

The otpme-tool command generates the CTP. That's what the OTPme roundcube plugin does on login. This way the child sessions for imap and smtp will use the secure CTP which will never be entered via keyboard which protects them against keylogger attacks.

Using CTPs is highly recommended if the application supports it. If you are a developer you can find infos about how to generate a CTPs, SLPs etc. at this site Howto_OTPme_my_site_

One last thing that should be mentioned here is NTLM authentication. OTPme supports it out of the box.

You can use otpme-token to generate a NTLM challange/response pair that can be used for testing. Normally this step is done by the client (e.g. notebook wlan client).

# otpme-token gen_ntlm testuser1/mobile-otp
NT_KEY: 4B08626DED20567648A3C1B09A35044C
NTLM_CHALLENGE: 3f58375faf829603
NTLM_RESPONSE: 97782e415a958e11d6790387147c15b3ac5bf277be9f95e3

Now we can test NTLM authentication.

# otpme-auth -d verify_ntlm testuser1 3f58375faf829603 97782e415a958e11d6790387147c15b3ac5bf277be9f95e3 roundcube
DEBUG: Processing ntlm authentication request.
DEBUG: Client 'roundcube' exists.
DEBUG: Got access group 'webmail' from client config.
DEBUG: Doing ntlm session verification.
DEBUG: Verifying session 'testuser1:webmail:ntlm:a8b911b3b06734d8f3374f70398aebee'.
DEBUG: No session found for this request.
DEBUG: Selecting user tokens based on access_group 'webmail'.
DEBUG: Selecting token 'mobile-otp' based on access group 'webmail'.
DEBUG: Will try the following otp tokens to verify this request: mobile-otp
DEBUG: Verifying static password tokens...
DEBUG: Verifying otp tokens...
DEBUG: Verifying token 'mobile-otp'.
DEBUG: Token 'mobile-otp' verified successful.
DEBUG: Adding OTP from this session to used OTPs of the user.
DEBUG: Found a valid session master: 'webmail'.
DEBUG: adding parent session 'testuser1:webmail:ntlm:e2426b33b59bba1846ee0c53950b00ca'
DEBUG: adding child session 'testuser1:imap:ntlm:4f3ca1526ab46154cfa3812c531676dc'.
DEBUG: adding child session 'testuser1:smtp:ntlm:59003b03133b91503bd8dc20a4f0712a'.
INFO: AUTH_OK_OTP: user=testuser1 token=mobile-otp access_group=webmail client=roundcube client_ip= auth_type=ntlm session=new:e2426b33b59bba1846ee0c53950b00ca
NT_KEY: 4B08626DED20567648A3C1B09A35044C

In case of an NTLM authentication request OTPme returns the NT_KEY instead of Accept/Reject.

NTLM authentication is supported with both, static password tokens and motp tokens. Also sessions, CTPs and SLPs are fully supported for NTLM authentication.

TODO: Add web-sso example!