Skip to content

KEYCLOAK-16134 Allow webauthn idless login flow#7860

Merged
mposolda merged 1 commit intokeycloak:mainfrom
vanrar68:webauthn-idless
Mar 21, 2022
Merged

KEYCLOAK-16134 Allow webauthn idless login flow#7860
mposolda merged 1 commit intokeycloak:mainfrom
vanrar68:webauthn-idless

Conversation

@vanrar68
Copy link
Copy Markdown
Contributor

Rework of a previously closed PR #7564 with changes requested by @mposolda
Prior to this PR WebAuthN authenticators (regular and passwordless) required a user to be set before asking for a webauthn device.
This PR removes the need for a user to be previously set when a webauthn credential containing a user id is submitted.

@abstractj abstractj added area/authentication Indicates an issue on Authentication area kind/feature Categorizes a PR related to a new feature labels Mar 17, 2021
@vanrar68
Copy link
Copy Markdown
Contributor Author

Added some modifications of the authenticator setup code in DefaultAuthenticationFlow.java.
Previously authenticator setup was only possible for authenticators that required users to be set (authenticator.requiresUser() == true). Now we also need to allow authenticator setup for authenticators that don't always require the user to be set.

@mposolda
Copy link
Copy Markdown
Contributor

mposolda commented Nov 16, 2021

@vanrar68 Sorry for late response. To me, the changes looks good.

TBH I would prefer to let them in once we have WebAuthn automated tests in place to make sure that our currently supported WebAuthn use-cases (with WebAuthn as 2nd-factor or passwordless) are not somehow broken by this change. We have PR for WebAuthn automated testing already in progress and hopefully will be added soon #8534 .

@tnorimat Does this change looks good to you or do you see any further issues with it?

@mposolda mposolda self-assigned this Nov 16, 2021
@mposolda mposolda requested a review from tnorimat November 16, 2021 12:48
@mposolda
Copy link
Copy Markdown
Contributor

@vanrar68 It will be also good to have some documentation for this. If you have an example how to integrate Keycloak with WebAuthn idless login, it will be nice to be added to the WebAuthn section of Keycloak documentation. Ideally details like:

  • How to configure Keycloak authentication flow and WebAuthn policies together with some info etc (Ideally with the usage of WebAuthn passwordless policy)
  • Which WebAuthn key you used for testing for idless (version, setup of the key if applicable etc).

@tnorimat
Copy link
Copy Markdown
Contributor

Hello @vanrar68 , @mposolda
I will review this PR today.

Copy link
Copy Markdown
Contributor

@tnorimat tnorimat Nov 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that L435 and L436 changes the original codes' logic for condition of throwing AuthenticationFlowException in L442.

To keep the same condition for throwing it in the original codes, how about the following?

    if (authUser != null && !authenticator.configuredFor(processor.getSession(), processor.getRealm(), authUser)) {
        if (factory.isUserSetupAllowed() && model.isRequired() && authenticator.areRequiredActionsEnabled(processor.getSession(), processor.getRealm())) {

If you intentionally changed this condition, could you tell me this reason?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of the modification is to handle credential setup for authenticators that don't require a user to be set. Your proposition looks good to me, I'll update the code accordingly in order to stay the closest possible to the existing code (though I think we should get rid of the meaningless comment line)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanrar68 Thank you. I've checked your update.

Copy link
Copy Markdown
Contributor

@tnorimat tnorimat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanrar68 I've added some review comments. Could you check them?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

processor.getAuthenticationSession().getAuthenticatedUser() can be replaced with authUser .

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, will do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanrar68 Thank you. I've checked your update.

@tnorimat
Copy link
Copy Markdown
Contributor

@vanrar68 As @mposolda has mentioned, the arquillian integration test for this ID-less WebAuthn login flow is needed.

@vanrar68
Copy link
Copy Markdown
Contributor Author

@vanrar68 As @mposolda has mentioned, the arquillian integration test for this ID-less WebAuthn login flow is needed.

Yes I agree, but as mentioned by @mposolda there seem to be some major work going on right now on webauthn testing framework, see #8534. I'd rather wait until this work is merged and implement the loginless test on top of that even if this means waiting some more to have loginless support in Keycloak. What do you think ?

@vanrar68
Copy link
Copy Markdown
Contributor Author

@vanrar68 It will be also good to have some documentation for this. If you have an example how to integrate Keycloak with WebAuthn idless login, it will be nice to be added to the WebAuthn section of Keycloak documentation. Ideally details like:

  • How to configure Keycloak authentication flow and WebAuthn policies together with some info etc (Ideally with the usage of WebAuthn passwordless policy)
  • Which WebAuthn key you used for testing for idless (version, setup of the key if applicable etc).

Yes, I'll create a PR for keycloak-documentation regarding the configuration of webauthn idless auth

@vanrar68 vanrar68 force-pushed the webauthn-idless branch 2 times, most recently from a56a316 to 6da8bfe Compare November 17, 2021 16:57
@tnorimat
Copy link
Copy Markdown
Contributor

@vanrar68

#7860 (comment)

Yes, I agree with you.

@vanrar68
Copy link
Copy Markdown
Contributor Author

@vanrar68 It will be also good to have some documentation for this. If you have an example how to integrate Keycloak with WebAuthn idless login, it will be nice to be added to the WebAuthn section of Keycloak documentation. Ideally details like:

  • How to configure Keycloak authentication flow and WebAuthn policies together with some info etc (Ideally with the usage of WebAuthn passwordless policy)
  • Which WebAuthn key you used for testing for idless (version, setup of the key if applicable etc).

@mposolda Does this need a JIRA/Github Issue to be opened on the keycloak-documentation project or is a PR enough ?

@mposolda
Copy link
Copy Markdown
Contributor

@vanrar68 As @mposolda has mentioned, the arquillian integration test for this ID-less WebAuthn login flow is needed.

Yes I agree, but as mentioned by @mposolda there seem to be some major work going on right now on webauthn testing framework, see #8534. I'd rather wait until this work is merged and implement the loginless test on top of that even if this means waiting some more to have loginless support in Keycloak. What do you think ?

+1 from me as well

@mposolda
Copy link
Copy Markdown
Contributor

@vanrar68 It will be also good to have some documentation for this. If you have an example how to integrate Keycloak with WebAuthn idless login, it will be nice to be added to the WebAuthn section of Keycloak documentation. Ideally details like:

  • How to configure Keycloak authentication flow and WebAuthn policies together with some info etc (Ideally with the usage of WebAuthn passwordless policy)
  • Which WebAuthn key you used for testing for idless (version, setup of the key if applicable etc).

@mposolda Does this need a JIRA/Github Issue to be opened on the keycloak-documentation project or is a PR enough ?

PR is enough. You can use the same JIRA in this PR to keycloak-documentation as you used in this PR.

@mposolda
Copy link
Copy Markdown
Contributor

mposolda commented Nov 18, 2021

@vanrar68 @tnorimat Thanks for the review Takashi and Thanks Joaquim for incorporating Takashi's feedback!

However I see there are failing tests and looks it may be regression of this PR. This may need to be investigated. I guess that is the consequence of the changes in the DefaultAuthenticationFlow. If it is possible to address this PR without changes in DefaultAuthenticationFlow, it will be great (Not 100% sure it is possible).

@vanrar68
Copy link
Copy Markdown
Contributor Author

@mposolda, @tnorimat
There's something else that would be interesting to have in Keycloak regarding loginless auth: the possibility for the user to select the auth method he wants to use before having to enter a username.
Currently, my understanding is that if the auth flow is configured with alternative "executions" AND the user has already submitted his username then Keycloak allows the user to select which of the alternative methods he wants to use (with the "Try another way" link) because the code in DefaultAuthenticationFlow.java builds a list of the available credentials for this user and matches these credentials with the authentication flow configuration.
With loginless auth it would be interesting to give the user the possibility to change the method of authentication ("Try another way") without having to enter a username. This way a user could choose between a Username/Password form or a WebAuthn Loginless auth. What do you think ?

@vanrar68
Copy link
Copy Markdown
Contributor Author

@vanrar68 @tnorimat Thanks for the review Takashi and Thanks Joaquim for incorporating Takashi's feedback!

However I see there are failing tests and looks it may be regression of this PR. This may need to be investigated. I guess that is the consequence of the changes in the DefaultAuthenticationFlow. If it is possible to address this PR without changes in DefaultAuthenticationFlow, it will be great (Not 100% sure it is possible).

I'll have a look

@vanrar68
Copy link
Copy Markdown
Contributor Author

@vanrar68 @tnorimat Thanks for the review Takashi and Thanks Joaquim for incorporating Takashi's feedback!

However I see there are failing tests and looks it may be regression of this PR. This may need to be investigated. I guess that is the consequence of the changes in the DefaultAuthenticationFlow. If it is possible to address this PR without changes in DefaultAuthenticationFlow, it will be great (Not 100% sure it is possible).

LOL, actually there is a way to have webauthn loginless without touching DefaultAuthenticationFlow: PR7564
The reason behind having to touch DefaultAuthenticationFlow is because we are diverting the "user requiring" WebAuthnPasswordless credential type to support Loginless auth (by making it not require a user anymore).

I'll have a look at the failing tests anyway

@mabartos mabartos removed the area/authentication Indicates an issue on Authentication area label Jan 20, 2022
@mposolda
Copy link
Copy Markdown
Contributor

Documentation PR: keycloak/keycloak-documentation#1306

@mposolda mposolda added area/authentication Indicates an issue on Authentication area area/docs and removed missing/docs area/authentication Indicates an issue on Authentication area labels Jan 21, 2022
@mabartos
Copy link
Copy Markdown
Contributor

@vanrar68 Thanks for the contribution! Before I review this PR, I'd like to discuss possible UI changes and improve usability of that. I created a discussion(#9821), so it'd be great if you'd share your thoughts or ideas.

@vanrar68
Copy link
Copy Markdown
Contributor Author

Includes an attempt at moving the "Try another way" link on the login page (before Identity Providers buttons).
@mabartos can you please have a look ?

@vanrar68
Copy link
Copy Markdown
Contributor Author

The failed tests are linked to the UI change not the idless feature itself

@mabartos
Copy link
Copy Markdown
Contributor

@vanrar68 Thanks for the update. I'll check it.

@vanrar68
Copy link
Copy Markdown
Contributor Author

vanrar68 commented Feb 24, 2022

This is my best (and last) shot at the UI:

try-another-way-1

try-another-way-2

try-another-way-3

try-another-way-4

@vanrar68
Copy link
Copy Markdown
Contributor Author

vanrar68 commented Mar 2, 2022

@mabartos did you get a chance to review to UI part of this PR ?

Copy link
Copy Markdown
Contributor

@mabartos mabartos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanrar68 Great work! In general, LGTM.

Just one nitpick with the parameter in the template.ftl file, which could be solved (see below). The design changes look good. The test itself looks good as well, but it needs some polishing, regarding new changes in the WebAuthn testsuite, in order to make it stable for a long time, but IMO, it might be solved in some follow-up task, where I can solve it. @mposolda WDYT?

I executed the pipeline tests for WebAuthn and they passed.
See https://keycloak-jenkins.com/job/universal-test-pipeline-server/1290/

(We need to focus only on the results for the specific test and browser Chrome... I verify the other failures are expected for this PR.)

@vanrar68 Thanks!

Comment thread themes/src/main/resources/theme/base/login/template.ftl Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if it's a proper solution to obtain sessionFactory in each iteration as the session (AFAIK) should be the same for the whole method. However, as one of the main purposes of the AuthenticationProcessor class is to manage the state of the authentication process and there are no other calls to dynamically changing objects, I don't consider this as a blocker for this PR. Just wanted to take it into consideration.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mabartos Something like this ? :

  KeycloakSessionFactory sessionFactory = processor.getSession().getKeycloakSessionFactory();
  typeAuthExecMap.forEach((key, value) -> {
      AuthenticatorFactory credbasedAuthenticatorFactory = (AuthenticatorFactory) sessionFactory.getProviderFactory(Authenticator.class, value.getAuthenticator());
      Authenticator credbasedAuthenticator = credbasedAuthenticatorFactory.create(processor.getSession());
      if (!credbasedAuthenticator.requiresUser()) {
          userlessCredBasedAuthenticationSelectionList.add(new AuthenticationSelectionOption(processor.getSession(), value));
      }
  });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I have sth like that in my mind, or maybe for the whole method. But I think you can keep it there as is. It might not have any performance issues.

@vanrar68
Copy link
Copy Markdown
Contributor Author

vanrar68 commented Mar 3, 2022

@mabartos just rebased to latest main and removed the showAnotherWayIfPresent from template.ftl as requested

mabartos
mabartos previously approved these changes Mar 3, 2022
Copy link
Copy Markdown
Contributor

@mabartos mabartos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanrar68 Thanks! LGTM

@tnorimat It'd be wonderful if you'd have a chance to review it as well?

And we need to wait for @mposolda approval.

@tnorimat
Copy link
Copy Markdown
Contributor

tnorimat commented Mar 3, 2022

@vanrar68 @mabartos Yes, I would like to review this PR.

Copy link
Copy Markdown
Contributor

@tnorimat tnorimat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanrar68 I've added one tiny comment. Could you check it?

@vanrar68
Copy link
Copy Markdown
Contributor Author

vanrar68 commented Mar 9, 2022

@mposolda did you get a chance to review this PR ?

Copy link
Copy Markdown
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanrar68 Did the review and testing and it looks good to me. Thanks for all your work on this!

@mposolda
Copy link
Copy Markdown
Contributor

@mabartos @tnorimat Thanks for your review and feedback!

@mposolda mposolda linked an issue Mar 21, 2022 that may be closed by this pull request
@mposolda mposolda merged commit 92c4e6d into keycloak:main Mar 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/authentication/webauthn area/docs kind/feature Categorizes a PR related to a new feature

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

Allow WebAuthn idless login flow

5 participants