Skip to content

Support one-time authorization code for form-based authentication mechanism #46974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

michalvavrik
Copy link
Member

@michalvavrik michalvavrik commented Mar 24, 2025

@michalvavrik michalvavrik requested a review from sberyozkin March 24, 2025 23:21
@quarkus-bot quarkus-bot bot added area/docstyle issues related for manual docstyle review area/documentation area/security area/vertx labels Mar 24, 2025

This comment has been minimized.

Copy link

github-actions bot commented Mar 25, 2025

🎊 PR Preview 0061772 has been successfully built and deployed to https://quarkus-pr-main-46974-preview.surge.sh/version/main/guides/

  • Images of blog posts older than 3 months are not available.
  • Newsletters older than 3 months are not available.

This comment has been minimized.

@michalvavrik
Copy link
Member Author

michalvavrik commented Mar 25, 2025

Update: Windows failure seems like a bug (though don't see how it is related to changes here), I'll find it and fix it.

@michalvavrik
Copy link
Member Author

Oh, it is failing because during merging I removed the fix I introduced to Quarkus main branch already, my bad, I'll drop it.

@sberyozkin
Copy link
Member

Thanks @michalvavrik, I'll look a bit later.

@michalvavrik michalvavrik force-pushed the feature/form-auth-one-time-token branch from 7c7b6b6 to 6db6efa Compare March 25, 2025 11:51
@michalvavrik
Copy link
Member Author

Thanks @michalvavrik, I'll look a bit later.

Thanks as well, no hurry, I expect this will take a longer discussion. But I think it is easier this way because it is less code to review and once this is in, JDBC part will be easy.

This comment has been minimized.

This comment has been minimized.

@sberyozkin
Copy link
Member

@michalvavrik Thanks, I've started commenting and we can continue in the next few days, I suggest to set it Draft for now as I guess there will be a few more iterations

@michalvavrik michalvavrik marked this pull request as draft March 25, 2025 17:51
@michalvavrik
Copy link
Member Author

As the PR is draft now, I'll be pushing changes continuously. I'll inform you with a PR comment once the PR is adapted to what we agreed in here and via email. Please ignore pushes until then.

@michalvavrik michalvavrik force-pushed the feature/form-auth-one-time-token branch 2 times, most recently from fff3113 to dbfe323 Compare March 29, 2025 12:40
@michalvavrik michalvavrik force-pushed the feature/form-auth-one-time-token branch from dbfe323 to c94c5f1 Compare April 2, 2025 23:31
@michalvavrik michalvavrik requested a review from sberyozkin April 2, 2025 23:32
@michalvavrik
Copy link
Member Author

@sberyozkin your turn :-)

@michalvavrik michalvavrik force-pushed the feature/form-auth-one-time-token branch from c94c5f1 to 55cf344 Compare April 16, 2025 18:51
[source,properties]
----
quarkus.http.auth.form.authentication-token.enabled=true
quarkus.http.auth.form.authentication-token.request-redirect-path=/authentication-token-form <1>
Copy link
Member

Choose a reason for hiding this comment

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

This path can be made a default value, quarkus.http.auth.form.authentication-token.enabled=true should be enough for such a case. Also propose to shorten the property to authentication-token.redirect-path

* This interface should be implemented as {@link jakarta.enterprise.context.ApplicationScoped}
* or {@link jakarta.inject.Singleton} CDI bean.
*/
public interface OneTimeAuthenticationTokenSender {
Copy link
Member

Choose a reason for hiding this comment

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

Would it be correct to name it FormAuthenticationTokenSender, with the one-time aspect highlighted in the docs ? Form authentication is the only built in mechanism that this interface can work with

import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;

final class OneTimeAuthTokenRequestHandler {
Copy link
Member

@sberyozkin sberyozkin Apr 26, 2025

Choose a reason for hiding this comment

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

Suggested change
final class OneTimeAuthTokenRequestHandler {
final class FormAuthenticationTokenRequestHandler {

or, FormAuthenticationTokenHandler

/**
* Event fired when Quarkus received one-time authentication token request.
*/
ONE_TIME_AUTH_TOKEN_REQUESTED
Copy link
Member

@sberyozkin sberyozkin Apr 26, 2025

Choose a reason for hiding this comment

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

I propose to propose to replace ONE_TIME (and lower cases onetime) everywhere with Form (using the right case), in this case it might be AUTHENTICATION_TOKEN (since it in the FormEventType), not sure _REQUESTED is necessary

@sberyozkin
Copy link
Member

Hi @michalvavrik, apologies for delaying reviewing it.

IMHO, it indeed looks better with the cookie.

I have a question, as it is not quite obvious to me from the PR.

  1. At what point do you create a session cookie in the PR ? If it is created before the user has to submit the token back to Quarkus, then it is problematic, because the user is already having a session cookie, without completing 2-factor, and can probably cancel the form and just access some secured endpoint path.

This may already be done this way, please clarify, but the way I imagine it should is as follows, if Form 2FA is enabled:

  • Redirect the user with the one time token cookie to the token submission form
  • Once the user token submission has been confirmed, remove the token cookie, create the session cookie

Do you agree ? Sorry if it is how it is already implemented

Thanks

[[two-factor-auth]]
==== Two-factor authentication

The form-based authentication mechanism supports two-factor authentication (2FA) with a one-time authentication token second-factor option.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The form-based authentication mechanism supports two-factor authentication (2FA) with a one-time authentication token second-factor option.
The form-based authentication mechanism supports two-factor authentication (2FA) with a one-time authentication token as a second-factor option.

----
<1> Once the one-time authentication token has been generated, redirect to a page with an authentication token form.

When user submit a username and password to the `/j_security_check` POST location, they will get relocated to the `/authentication-token-form` page.
Copy link
Contributor

@MichalMaler MichalMaler May 14, 2025

Choose a reason for hiding this comment

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

Suggested change
When user submit a username and password to the `/j_security_check` POST location, they will get relocated to the `/authentication-token-form` page.
After users post their username and password to `/j_security_check`, they are redirected to `/authentication-token-form`.


The form-based authentication mechanism supports two-factor authentication (2FA) with a one-time authentication token second-factor option.

.Enable two-factor authentication
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
.Enable two-factor authentication
* To enable 2FA, set the following properties:
+

quarkus.http.auth.form.authentication-token.enabled=true
quarkus.http.auth.form.authentication-token.request-redirect-path=/authentication-token-form <1>
----
<1> Once the one-time authentication token has been generated, redirect to a page with an authentication token form.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<1> Once the one-time authentication token has been generated, redirect to a page with an authentication token form.
<1> After generating the one-time authentication token, redirect to the authentication token form.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hello Michal! Not sure if we need to use the <1> here. If not, I would just use the "+" above that sentence to glue and align it to that snippet above, and we should be good. It's a way to describe the aftermath of our earlier actions.

<1> Once the one-time authentication token has been generated, redirect to a page with an authentication token form.

When user submit a username and password to the `/j_security_check` POST location, they will get relocated to the `/authentication-token-form` page.
The `/authentication-token-form` page should allow users to submit the one-time authentication token sent to them.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The `/authentication-token-form` page should allow users to submit the one-time authentication token sent to them.
The `/authentication-token-form` page allows them to submit the one-time authentication token.

When user submit a username and password to the `/j_security_check` POST location, they will get relocated to the `/authentication-token-form` page.
The `/authentication-token-form` page should allow users to submit the one-time authentication token sent to them.

.Example form for authentication with a one-time authentication token
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
.Example form for authentication with a one-time authentication token
.An example of an HTML form that submits a one-time authentication token


Once Quarkus has generated the one-time authentication token, you need to deliver the token to a user by declaring a CDI bean that implements the `io.quarkus.vertx.http.security.token.OneTimeAuthenticationTokenSender` interface.

.Example one-time authentication token sender
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
.Example one-time authentication token sender
.An example of a CDI bean that sends the one-time authentication token by email

}
----
<1> Use the Quarkus Mailer extension to send the email with the authentication token.
See the xref:mailer-reference.adoc[Quarkus Mailer Reference documentation] for more information about the mailer.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
See the xref:mailer-reference.adoc[Quarkus Mailer Reference documentation] for more information about the mailer.
For more information about the mailer, see the xref:mailer-reference.adoc[Quarkus Mailer reference documentation].

@MichalMaler
Copy link
Contributor

Hey, @michalvavrik ! I just spotted this awesome PR and provided a few suggestions. Use them if you like it, or feel free to tweak them or drop them completely :)
Kind regards, Michal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants