privacyidea/keycloak-provider

Token selection

gryffus opened this issue · 15 comments

Hello, I have some issues with the PI keycloak provider and I would like to ask if they are fixable.

  1. Poll interval: It seems, that the browser poll interval for checking of the valid PUSH token is too long (10 seconds?). Is it possible to change the interval to 1-3 seconds, so user does not have to wait too long after accepting the PUSH token on their device?

  2. When user does not have any OTP token configured, there is still a button to use OTP token. This should be disabled if no OTP token exists:
    obrazek

  3. When user has OTP and PUSH tokens configured, the UI is wrong.
    a) When "Preferred Login Token Type = PUSH", user is still presented with "enter your OTP" window first, with possibility to switch to Push in "alternate login methods". I.e. the "Preferred Login Token Type" setting seems to have no effect.
    b) User still gets the PUSH request in the OTP window. After approving the PUSH request, user is not logged in until he switches to Push in "alternate login methods". Also, after switching to Push in "alternate login methods", the user gets second Push request. This is very confusing for the users.

  4. When user declines the Push token auth. The UI is still in the waiting state. Is it possible to show something like "Push auth declined" ?

Thanks for any explanations.

Hello,

  1. You can set the intervals for polling in the settings
  2. We do not know if the user has no OTP token configured, we only get the information about the ones that were triggered. This does not neccessarily include all token the user has.
    3a) What version of the server and provider are you using?
    3b) The push request is triggered before anything of the keycloak UI is shown. The user then has to chose with which token to authenticate, so yes they have to press push to use their push token.
    You need to check where the second push request is coming from. Like i said, the requests are triggered before the UI is shown. You can enable logging in the keycloak provider to see in the log what is sent to the server and likewise in the server to log when requests are triggered.
  3. It is currently not possbile for any application to get information about the decline, so the application (keycloak provider) can not distinguish between not accepted and declined.

Sorry, I don't know how I could miss the polling setting :x

Versions:
keycloak: 21.0.2
keycloak-provider: 1.2.0.KC21
privacyidea: 3.8.1

Currently, it seems to work in a way, that all tokens are triggered on the OTP step at once, no matter which option the user choose.

Example.

User has configured 3 tokens. 1. PUSH 2. SMS 3. TOTP

Request to privacyidea:

keycloak_1     | 2023-04-18 22:42:07,934 INFO  [org.privacyidea.authenticator.PrivacyIDEAAuthenticator] (pool-9-thread-1) PrivacyIDEA Client: POST /auth
keycloak_1     | 2023-04-18 22:42:07,934 INFO  [org.privacyidea.authenticator.PrivacyIDEAAuthenticator] (pool-9-thread-1) PrivacyIDEA Client: username=privacyidea
keycloak_1     | 2023-04-18 22:42:07,934 INFO  [org.privacyidea.authenticator.PrivacyIDEAAuthenticator] (pool-9-thread-1) PrivacyIDEA Client: password=******************
keycloak_1     | 2023-04-18 22:42:07,935 INFO  [org.privacyidea.authenticator.PrivacyIDEAAuthenticator] (pool-9-thread-1) PrivacyIDEA Client: realm=administrators
keycloak_1     | 2023-04-18 22:42:09,086 INFO  [org.privacyidea.authenticator.PrivacyIDEAAuthenticator] (pool-9-thread-1) PrivacyIDEA Client: POST /validate/triggerchallenge
keycloak_1     | 2023-04-18 22:42:09,086 INFO  [org.privacyidea.authenticator.PrivacyIDEAAuthenticator] (pool-9-thread-1) PrivacyIDEA Client: user=lukas.krejza
keycloak_1     | 2023-04-18 22:42:10,787 INFO  [org.privacyidea.authenticator.PrivacyIDEAAuthenticator] (OkHttp https://brn-qa-otp.sa.cz/...) PrivacyIDEA Client: /validate/triggerchallenge:
keycloak_1     | {
keycloak_1     |   "detail": {
keycloak_1     |     "attributes": {
keycloak_1     |       "hideResponseInput": true
keycloak_1     |     },
keycloak_1     |     "client_mode": "interactive",
keycloak_1     |     "message": "Enter the OTP from the SMS:, Please confirm the authentication on your mobile device!, please enter otp: ",
keycloak_1     |     "messages": [
keycloak_1     |       "Enter the OTP from the SMS:",
keycloak_1     |       "Please confirm the authentication on your mobile device!",
keycloak_1     |       "please enter otp: "
keycloak_1     |     ],
keycloak_1     |     "multi_challenge": [
keycloak_1     |       {
keycloak_1     |         "attributes": {
keycloak_1     |           "valid_until": "2023-04-19 00:47:10.261764"
keycloak_1     |         },
keycloak_1     |         "client_mode": "interactive",
keycloak_1     |         "message": "Enter the OTP from the SMS:",
keycloak_1     |         "serial": "PISM00001F27",
keycloak_1     |         "transaction_id": "10965001180883353020",
keycloak_1     |         "type": "sms"
keycloak_1     |       },
keycloak_1     |       {
keycloak_1     |         "attributes": {
keycloak_1     |           "hideResponseInput": true
keycloak_1     |         },
keycloak_1     |         "client_mode": "poll",
keycloak_1     |         "message": "Please confirm the authentication on your mobile device!",
keycloak_1     |         "serial": "PIPU00038ABC",
keycloak_1     |         "transaction_id": "10965001180883353020",
keycloak_1     |         "type": "push"
keycloak_1     |       },
keycloak_1     |       {
keycloak_1     |         "client_mode": "interactive",
keycloak_1     |         "message": "please enter otp: ",
keycloak_1     |         "serial": "TOTP0000F288",
keycloak_1     |         "transaction_id": "10965001180883353020",
keycloak_1     |         "type": "totp"
keycloak_1     |       }
keycloak_1     |     ],
keycloak_1     |     "serial": "TOTP0000F288",
keycloak_1     |     "threadid": 140532767864576,
keycloak_1     |     "transaction_id": "10965001180883353020",
keycloak_1     |     "transaction_ids": [
keycloak_1     |       "10965001180883353020",
keycloak_1     |       "10965001180883353020",
keycloak_1     |       "10965001180883353020"
keycloak_1     |     ],
keycloak_1     |     "type": "totp",
keycloak_1     |     "preferred_client_mode": "interactive"
keycloak_1     |   },
keycloak_1     |   "id": 2,
keycloak_1     |   "jsonrpc": "2.0",
keycloak_1     |   "result": {
keycloak_1     |     "authentication": "ACCEPT",
keycloak_1     |     "status": true,
keycloak_1     |     "value": 3
keycloak_1     |   },
keycloak_1     |   "time": 1681857730.7202284,
keycloak_1     |   "version": "privacyIDEA 3.8.1",
keycloak_1     |   "versionnumber": "3.8.1",
keycloak_1     |   "signature": "rsa_sha256_pss:<***>"
keycloak_1     | }

Now user is "spammed" by both SMS and firebase notification.

This UI is shown:

obrazek

i.e. user is prompted for OTP, but he gets PUSH notification too. If he approves the PUSH notification, nothing happens.

Now, when user wants to use PUSH instead of OTP, he needs to click on "push" button. In case he didn't approve the first request, he now gets second one and needs to click approve twice, leading to even more confusion.

What I would like to propose / accomplish is one of.

  1. Show the "Please confirm the authentication on your mobile device!" screen first

  2. Send PUSH notification with the first screen

  3. Send SMS OTP only after clicking on "One-Time-Password" button

Or

  1. Do the polling in one window, without user having to click on "push"

Or (less preferred)

  1. Do not send PUSH notification unless user clicks on the "push" button

If you use triggerchallenge, all token of the user will be triggered, because it is done as "admin action".

Triggering the token "on demand" is possible if the user enters the corresponding PIN of the token that should be triggered as otp - assuming triggerchallenge is disabled then. Triggering on demand like you proposed is very cumbersome, we might do something like that someday, but most users only have 1 token type, 2 at max, so it is not really in demand.

In any case, the token are triggered only once, so if your user does get 2 push requests there is something wrong somewhere else. You should be able to see from the keycloak log of the provider that there is only 1 request triggering the token. If you press push, nothing really happens, it only reloads the UI.

If you want to "Show the "Please confirm the authentication on your mobile device!" screen first", you can set the preferred_client_mode to "push" so the plugin will be in push mode first (if push was triggered). You can set that in keycloak plugin settings (deprecated but still there), or in the server via policy (>3.8).

"Do the polling in one window, without user having to click on "push"", we are working on this. But it will be optional, since it is not always possible for the browser of the user to reach the polling endpoint of the privacyIDEA instance.

Ok, I have tried to disable triggerchallenge and I still do not see any possible way to enter PIN of the token to choose correct one. It now only asks for OTP without possibility to switch to PUSH or even information which OTP type to use (SMS, TOTP, ...)

Where should the user enter PIN of the corresponding token?

I have reinstalled whole stack and now I am getting only one PUSH notification (with triggerchallenge, as mentioned above), so that was probably a misconfiguration on one of the balancing proxies.

preferred_client_mode is of course set to "PUSH", but first token it asks for is always OTP (with triggerchallenge... without triggerchallenge PUSH is not even offered)

Also, I have found, that in clustered setup, when token response goes to different keycloak instance than was requested, it fails, but only once. Once each of the clustered instances does at least one token request to privacyidea, it works fine. I guess I should create separate bug report for this?

The PIN can be entered in the OTP field which will trigger the corresponding token.

If you have problems in a clustered setup, you will have to generate the information/idea for what the problem is, i have no time to test that.

Ok, perhaps I am missing something fundamental here.

This is the message that user see when "sending password" enabled and "challenge response" disabled:
obrazek

How can the user enter his token PIN? Is there a way to implement the token selection as an actual UI element (dropdown menu, buttons) as seen elsewhere?

I was able to identify and reproduce the clustering problems i had and created separate issue for that (#139). Let's keep this one for the token selection. Sorry for confusion.

The PIN can be entered in the field of your screenshot, instead of the OTP. If the PIN triggers the correspoding OTP, the user will be prompted again for the actual OTP value.

It could be implemented to show the token of the user before, but that would require an admin account/authtoken in all cases and make this provider unneccessarily complicated. Therefore we do not plan to implement this currently.

Im going to close this issue now because it seems to work as intended.

If we develop the token selection ourselves, will the SR be accepted?

To me, the current way of choosing tokens is not ergonomic (also, user has no way of knowing, that he can use a PIN in the OTP field to trigger a specific token). There is also no information about it, both for the admins / integrators and both for the users in the UI. (For example "Enter OTP from any source or enter PIN of a specific token to trigger it").

Thinking about it, why would user enter a pin of specific token, when all tokens are triggered already? This seems like a nonsense.

Therefore, we would like to develop the change ourselves, so the authentication flow is clear for the user, when multiple tokens are enrolled.

Would patch like that be accepted? Can you give us some guidance how would you like us to implement it so it can be accepted?

Thanks.

@nilsbehlen Does this project have IRC so we can discuss it in realtime?

We dont have IRC.
Of course you can implement it and if there is a real benefit to it we would accept it.
I just read the text in this issue again and im not sure we are understand each other correctly.
Your point 3b from the original post is right, we created #136 for that.
What is the login process you want to achieve?

I want to let user choose which token they want to use, via icons.

My goal would be to split the 2FA step into two.

  1. First step would fetch available tokens from privacyidea and show available tokens as icons to user.
  2. After user clicks on one of the icons (each representing a token), the respective token gets triggered.

Currently, there is no clear information for the user, that he can use PIN of a token instead of the OTP to trigger specific token and even if it would, the tokens are already triggered in that step, so there is really no reason to trigger specific token in that step. Our users have 3 tokens: SMS, TOTP and PUSH and current process is confusing for them. All tokens get triggered at once, so they get PUSH notification, SMS in addition to their configured TOTP token. Moreover, our users do not have token PINs that they would need to remember. We want to distinguish tokens based on type or serial to not force users to set token PINs and trigger them this way.

Check this example from another 2FA solution: https://help.duo.com/servlet/rtaImage?eid=ka04u000000QjjG&feoid=00N700000039b6e&refid=0EM0g0000014x1F

We would like to extend this in the future to support also other token types, like for example tiqr, but that is not in the current scope.

Also the preferred_client_mode does not seem to have any effect, but we more or less decided to implement the token selection on our own, so that would make this problem obsolete.

I dont think there is much benefit to having a token selection for us, because it would require alot of changes to the code. If you need it for your scenario, you will have to fork this project.

Also the preferred_client_mode does not seem to have any effect, but we more or less decided to implement the token selection on our own, so that would make this problem obsolete.

Did you set it in the plugin or in the server? It can be set in both (server >=3.8) and the server overwrites the plugin behavior.

Hmm, can you please point me to the correct policy for the preferred_client_mode server setting? I was trying to find it, but was unsuccessful.

scope: authentication, misc->preferred_client_mode