privacyidea / keycloak-provider

:lock: OTP Two Factor Authentication Provider for Keycloak to run with privacyIDEA
Apache License 2.0
78 stars 23 forks source link

preferred_client_mode always otp in polling mode #150

Closed gryffus closed 1 year ago

gryffus commented 1 year ago

Hello,

I know this is fast :) but with latest patches for the polling mode and Keycloak 22.0.1, the default UI is always the OTP one.

If I turn off the polling mode https://github.com/privacyidea/keycloak-provider/issues/133 in settings, it correctly shows preferred mode, which is currently poll (PUSH).

Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]: 2023-07-31 19:34:29,216 INFO  [org.privacyidea.authenticator.PrivacyIDEAAuthenticator] (OkHttp https://privacyidea.acme.org/...) PrivacyIDEA Client: /validate/triggerchallenge:
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]: {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   "detail": {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "attributes": {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       "hideResponseInput": true
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     },
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "client_mode": "interactive",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "message": "Enter the OTP from the SMS:, Please confirm the authentication on your mobile device!, please enter otp: ",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "messages": [
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       "Enter the OTP from the SMS:",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       "Please confirm the authentication on your mobile device!",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       "please enter otp: "
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     ],
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "multi_challenge": [
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "attributes": {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:           "valid_until": "2023-07-31 21:39:28.587034"
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         },
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "client_mode": "interactive",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "message": "Enter the OTP from the SMS:",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "serial": "PISM0002B2FA",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "transaction_id": "10640560423853690839",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "type": "sms"
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       },
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "attributes": {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:           "hideResponseInput": true
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         },
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "client_mode": "poll",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "message": "Please confirm the authentication on your mobile device!",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "serial": "PIPU0000478D",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "transaction_id": "10640560423853690839",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "type": "push"
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       },
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "client_mode": "interactive",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "message": "please enter otp: ",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "serial": "TOTP000178F0",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "transaction_id": "10640560423853690839",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:         "type": "totp"
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       }
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     ],
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "serial": "TOTP000178F0",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "threadid": 139909752108800,
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "transaction_id": "10640560423853690839",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "transaction_ids": [
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       "10640560423853690839",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       "10640560423853690839",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:       "10640560423853690839"
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     ],
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "type": "totp",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "preferred_client_mode": "poll"
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   },
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   "id": 2,
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   "jsonrpc": "2.0",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   "result": {
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "authentication": "ACCEPT",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "status": true,
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:     "value": 3
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   },
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   "time": 1690832069.0865915,
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   "version": "privacyIDEA 3.8.1",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   "versionnumber": "3.8.1",
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]:   "signature": "rsa_sha256_pss:51a5adf64a0d63b25ea9d586d7c8434337f1e02cb9a4f9f461ad2243090ae85d0f129b534acc646b1da429064cc1494316fa2b87a99e68a31a6085e26c04d2fbcea66468ea24f52c8b590797000c4ba0605191afff5aedf06751060a0a8ea7d6b4374c008d86a563d4bf9291028bd6396afce32d08432aeb4b2d78c46efdf93aed2d276f0535275dba3e8d576aef1bc3a352462b5d28b1ccb03af8fe568593d51dcc4b46719c414a9816697917df5366d3b5330af7de31aa5e6517897062e705b65310b959cff69098dc14ea29d3a817cb8b120d30010aea31c3e213e0452a51aab90f8143c2a4fcd3fd02b6835bbdf1d96357cd8cda3766744604801c07d413"
Jul 31 21:34:29 localhost docker/opt_keycloak_1[526851]: }

Let me know if you need any other info.

nilsbehlen commented 1 year ago

That is the intended behavior. What is the problem? If your setup is right to use poll-in-browser, there are no "modes" anymore because the polling is done in the background. If there is an error (you can check with dev tools console), it will default to OTP, showing the push button. In that case u can either disable it or make it work.

gryffus commented 1 year ago

Hello,

when polling mode is disabled, this is the default/first UI shown:

obrazek i.e. keycloa-provider correctly uses "preferred_client_mode" configured in PrivacyIDEA. This is the correct behaviour.

However, after I enable polling mode, this is the default/first UI shown: obrazek

So there are technically 2 problems:

1) Same Origin Policy violation (causing the fallback to non-polling mode)

2) Fallback should use the same code path as without the polling patch, hence should respect PrivacyIDEA's "preferred_client_mode"

nilsbehlen commented 1 year ago

The feature is experimental, we are testing if this has any benefit for users/admins and how it is used. If it does not have any, we will remove it and not implement it elsewhere. It requires that the admin makes sure it works, e.g. solving your problem 1. The fallback can not use the "same code path" because the site does not refresh -> keycloak provider code is not executed. The fallback is not meant to be the permanent state, it is literally a fallback so that a login is still possible.

gryffus commented 1 year ago

I am acknowledge that this is an experimental feature and this is actually the reason why I am testing it and reporting issues so soon. We are very excited for this to work and we aim for using this polling mode as a basis of the intuitive (button) token selection implementation. Getting rid of switching between polling and otp modes is very feasible.

You mention problem 1 being "my" problem. Is the polling mode intended to be used with Same Origin Policy being turned off? This would make the keycloak instance vulnerable to XSS, or am I mistaken? Do you test it without Same Origin Policy?

Is there any technical or fundamental reason, why it does not correctly respect "preferred_client_mode" or is it simply not implemented (yet) ?

nilsbehlen commented 1 year ago

Since i am not an admin or webdev, i do not know that much about network setups etc. I think depending on your domains, you would not need to "disable" (rather adjust) the CORS settings, because it would not be cross-origin. This is not something we can get around if we want the browser of the user to access privacyidea directly. So you either have to setup your infrastructure in a way that it works, which might be stupid in some cases, or you have to adjust the CORS settings (e.g. to allow GET requests from a users browser, maybe identified by IP range). I also don't really see how CORS is directly related to XSS? CORS is meant to protect resources (privacyidea) from unauthorized outside access (user browser). Obviously you should not set it to *, the proper setting depends on your setup. Like i mentioned, only GET requests are required for this to work.

The reason preferred_client_mode does not work with the fallback is that the mode of the ui is set by the provider code running in keycloak. The preferred mode is not passed to the ui, rather the provider code sets the state of the ui. And since the ui does not reload when an error for poll-in-browser is detected, the provider code can not set the ui again. Of course this could be done like you said, but for the first release our idea was: Either you make it work or you disable it and not to a elaborate fallback. If i have some time left before the release of 1.3.0, i will see if i can improve it.

gryffus commented 1 year ago

After configuring it on the privacyIDEA webserver side, the polling mode works. Sorry for confusion, i confused it with "Origin" keycloak client setting, which is related to the client resources access, not to the actual login process.

Nothing is also required to turn off, just enable the keycloak server as an origin, like you said. Example for apache: Header set Access-Control-Allow-Origin "https://<keycloak.acme.org>"

Of course you need to enable mod_headers for that to work.

Thanks for the hint. The new mode is awesome, by the way! :)

I guess we now need https://github.com/privacyidea/keycloak-provider/issues/137 for the UI to not look like this: obrazek

I.e. something like "Please accept login with your device, or enter OTP:" would be nice. Question is how to do it translatable? Or maybe just rename "Alternate login methods" to "Or please accept login with your device/alternate login method".

Thanks for explaining the fallback mode and it absolutely makes sense to fix/improve it after 1.3.0. I must say the 1.3.0 is starting to shape pretty nicely, so far by the way! :) Thanks.

nilsbehlen commented 1 year ago

The message is directly taken from the response from privacyidea. It should be configurable there somehow, but it probably will still put an , between the message for each token when they are aggregated. The idea for #137 was originally to just replace the first default message. What you are seeing is the challenge-message, which would overwrite the #137 setting. However, we could make that permanent (optionally) so that challenge messages would be discarded and it always shows the message configured.

gryffus commented 1 year ago

Showing the JSON token messages is the correct way I think, that way internationalization works (well, once privacyidea fixes that )

However, in the JSON there are 3 messages: 1) Enter the OTP from the SMS: 2) Please confirm the authentication on your mobile device! 3) please enter otp:

In the UI, you can see only 2 of them (the OTP ones). The 2) message is not displayed at all.

Also, what about the "Alternate login methods" text? This one is not from the JSON and does not make sense in the browser-polling mode.

nilsbehlen commented 1 year ago

Also, what about the "Alternate login methods" text? This one is not from the JSON and does not make sense in the browser-polling mode.

There might be webauthn, but the text should only be shown when there is. We will need to improve the UI stuff, maybe unify it for everything that uses HTML/js, since there is alot more going on now than just 3 input fields.