Skip to content
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

Unset session data when disabling all providers to prevent fatal #566

Closed
wants to merge 9 commits into from

Conversation

iandunn
Copy link
Member

@iandunn iandunn commented May 12, 2023

Fixes #565

Unsets the 2FA session data when all providers are disabled, so that the user's current session is no longer considered a 2FA session. That avoids the fatal error, and allows them to enable a provider again.

Testing Instructions

Repeat the reproduction steps from #565.

Changelog Entry

None needed, because #529 has not been released yet.

@iandunn iandunn force-pushed the reauth-no-providers-fatal branch from 14695f3 to a312fa3 Compare May 13, 2023 00:03
@iandunn
Copy link
Member Author

iandunn commented May 13, 2023

This is working in my tests for wp-admin, but not yet for 3rd party clients that use the REST API endpoints.

Maybe we should provide a new endpoint to update the session, and it'd be their responsibility to call it? It seems like an internal detail that should be handled automatically, though 🤔

@dd32
Copy link
Member

dd32 commented May 15, 2023

What about changing is_current_user_session_two_factor() to be false when the user has no 2FA providers active?

Another other option would be to alter current_user_can_update_two_factor_options():
https://github.com/dd32/two-factor/blob/9032f2d825623df58542e4f9d8968bc86b95698a/class-two-factor-core.php#L1126-L1129

 		// If the current user is not a two-factor user, not having a two-factor session is okay.
-		if ( ! self::is_user_using_two_factor( $user_id ) && ! $is_two_factor_session ) {
+		if ( ! self::is_user_using_two_factor( $user_id ) ) {
 			return true;
 		}

This feels somewhat expected, I'm not sure why the additional conditional is included there

Copy link
Member

@dd32 dd32 left a comment

Choose a reason for hiding this comment

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

I've taken this in a slightly different direction via #567 but adding my thoughts inline here.

Comment on lines +153 to +157
// this doesn't call user_two_factor_options_update()
// maybe the custom ui should do that? well i guess it cant
// it's probably appropriate for this func to do that

// same for other rest api endpoints that update providers
Copy link
Member

Choose a reason for hiding this comment

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

In the context of the two-factor plugin as it stands today, the provider being setup/reset probably doesn't warrant the session changing.

My reasoning for that is that these only control the Provider details, it doesn't affect the actual enabled providers for the user, even though they should likely be far more tightly coupled. The UI and design of two-factor has them as very distinct components, where as wporg-two-factor has them far more coupled.

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps converting the XHR endpoints to REST API methods was poorly thought out, and instead it should've been something more generic, which ran through a centralised Two_Factor_Core handler that decided what the request did, removing the providers from the equation.

# Details about 2FA
GET /me/two-factor
{ enabled: [ two_factor_dummy ], available: { two_factor_email: [ param1, param2 ] } }

# Setup a 2FA
POST /me/two-factor
{ provider: two_factor_totp, { param1: ..., ... } }

# Reset / Deactivate
DELETE /me/two-factor
{ provider: two_factor_dummy }

Comment on lines +1852 to +1854
// ! $existing_providers &&
// does it matter that they were existing? is it enough to just say "if there are some, then..."
// test still pass w/ this commented out
Copy link
Member

Choose a reason for hiding this comment

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

The main intention would not to extend their 2fa grace time by simply constantly enabling and disabling an additional provider I think

Comment on lines +899 to +900
$this->assertArrayNotHasKey( 'two-factor-login', $session );
$this->assertArrayNotHasKey( 'two-factor-provider', $session );
Copy link
Member

Choose a reason for hiding this comment

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

I guess at the time I thought something like "The fact the user is no longer logged in with 2FA doesn't suddenly make their session not a 2fa session", but somewhere along the line with the logic changes I've missed that they couldn't then update the session after disabling it..

@iandunn
Copy link
Member Author

iandunn commented May 15, 2023

What about changing is_current_user_session_two_factor() to be false when the user has no 2FA providers active?

That way my first approach, but it felt like a smell to leave the the raw session data in an incorrect state. I worried that it could lead to confusion and maybe even bugs in the future.

...alter current_user_can_update_two_factor_options() [to remove && ! $is_two_factor_session]

That seems fine to me regardless 👍🏻

@iandunn
Copy link
Member Author

iandunn commented May 19, 2023

Fixed by #567

@iandunn iandunn closed this May 19, 2023
@jeffpaul jeffpaul deleted the reauth-no-providers-fatal branch December 2, 2024 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Revalidation required when no providers enabled
2 participants