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

New class for state handling; set cookie for implicit nonce #458

Merged
merged 1 commit into from
May 10, 2018

Conversation

joshcanhelp
Copy link
Contributor

@joshcanhelp joshcanhelp commented May 4, 2018

  • Refactored state and nonce handling to extend a WP_Auth0_Random_Storage class.
  • Set a nonce cookie for implicit logins during Lock init
  • Set a nonce cookie for implicit auto-logins before redirect
  • Renamed methods to conform to WP code standards

@joshcanhelp joshcanhelp added this to the 3.6.0 milestone May 4, 2018
@@ -1,134 +1,24 @@
<?php

final class WP_Auth0_Nonce_Handler {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Move to parent class

@@ -0,0 +1,121 @@
<?php

class WP_Auth0_Random_Storage {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was previously the WP_Auth0_Nonce_Handler. I added a more generic cookie name and removed the verify method so extending classes can implement it themselves.

if ( $this->query_vars( 'error' ) || $this->query_vars( 'error_description' ) ) {
$error_msg = sanitize_text_field( rawurldecode( $_REQUEST[ 'error_description' ] ) );
$error_code = sanitize_text_field( rawurldecode( $_REQUEST[ 'error' ] ) );
if ( ! empty( $_REQUEST['error'] ) || ! empty( $_REQUEST['error_description'] ) ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

query_vars was causing problems in the state retrieval so I changed that here as well.

@@ -228,8 +217,7 @@ public function redirect_login() {

// Look for clues as to what went wrong.
$e_message = ! empty( $data->error_description ) ? $data->error_description : __( 'Unknown error', 'wp-auth0' );
$e_code = ! empty( $data->error ) ? $data->error : $exchange_resp_code;
throw new WP_Auth0_LoginFlowValidationException( $e_message, $e_code );
throw new WP_Auth0_LoginFlowValidationException( $e_message, $exchange_resp_code );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Didn't like the string error code ... found during debugging

@@ -608,30 +595,30 @@ public static function get_userinfo_scope( $context = '' ) {
* @return array
*/
public static function get_authorize_params( $connection = null, $redirect_to = null ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mainly whitespace changes in this method

@joshcanhelp joshcanhelp force-pushed the change-state-and-nonce-handling branch 2 times, most recently from f52c688 to 2bf199a Compare May 9, 2018 17:12
Copy link
Contributor

@lbalmaceda lbalmaceda left a comment

Choose a reason for hiding this comment

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

I'd like to discuss the inheritance of the new storage classes with you.

$auth_params = self::get_authorize_params( $connection );

$auth_url = 'https://' . $this->a0_options->get( 'domain' ) . '/authorize';
$auth_url = add_query_arg( array_map( 'rawurlencode', $auth_params ), $auth_url );

setcookie( WPA0_STATE_COOKIE_NAME, $auth_params['state'], time() + WP_Auth0_Nonce_Handler::COOKIE_EXPIRES, '/' );
WP_Auth0_State_Handler::get_instance()->setStateCookie( $auth_params['state'] );
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this line doesn't check for isset (state) because state is ALWAYS sent, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct. That array comes from the get_authorize_params() method in this same class and is always generated.

@@ -326,7 +314,7 @@ public function implicit_login() {

// Validate the nonce if one was included in the request if using auto-login.
$nonce = isset( $decoded_token->nonce ) ? $decoded_token->nonce : null;
if ( ! WP_Auth0_Nonce_Handler::getInstance()->validate( $nonce ) ) {
if ( ! WP_Auth0_Nonce_Handler::get_instance()->validate( $nonce ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

are you following the same method naming convention everywhere? Asking since I see a misxture for class names, i.e. WP_Auth0_LoginFlowValidationException

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For new methods, I'm following the WP standard, which is snake-case. There was no naming convention, really, up until now.

/**
* Contains WP_Auth0_Nonce_Handler.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm seeing 2 docs for this class definition. Should they be merged?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a file and a class comment. Duplicative but part of the code quality scan.

* @var WP_Auth0_Nonce_Handler|null
*/
protected static $_instance = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to make it protected.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I actually think that I do in this case. The classes that extend WP_Auth0_Random_Storage use late static binding to call the child class from the parent (static when you see that). A private property here would affect how that functions. If I switch these to private, I get:

Fatal error: Access level to WP_Auth0_Nonce_Handler::$_instance must be protected (as in class WP_Auth0_Random_Storage) or weaker in /Users/josh-cunningham/Sites/wp-auth0-v1/wp-content/plugins/auth0/lib/WP_Auth0_Nonce_Handler.php on line 12

... and they cant be public so there we are.

Copy link
Contributor

Choose a reason for hiding this comment

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

you already have a getInstance method (the singleton getter) on the super class. Use that from the child ones.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I do have that and do use that but the child classes need to have an _instance property for that to work.

*
* @var WP_Auth0_State_Handler|null
*/
protected static $_instance = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to make it protected.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See above ☝️

final class WP_Auth0_State_Handler extends WP_Auth0_Random_Storage {

/**
* Cookie name used to store nonce
Copy link
Contributor

Choose a reason for hiding this comment

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

nonce or state?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nonce is correct in this case. This nonce is added to a state object

const UNIQID_COOKIE_NAME = 'auth0_state_uniqid';

/**
* Cookie name used to store nonce
Copy link
Contributor

Choose a reason for hiding this comment

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

nonce or state?

* @var string
*/
const UNIQID_COOKIE_NAME = 'auth0_nonce_uniqid';
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this be called NONE_COOKIE_NAME or even COOKIE_NAME? Since it's already inside the nonce handler class

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Synonymous as used. The uniqid is used as a nonce in the Nonce class.

*
* @var string
*/
const STATE_COOKIE_NAME = 'auth0_state';
Copy link
Contributor

Choose a reason for hiding this comment

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

wait, what's the difference between this one and the uniqid one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

State is state, nonce is the salt in state.

*
* @return bool
*/
public function validate() {
Copy link
Contributor

Choose a reason for hiding this comment

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

see my long comment over class inheritance and protected methods.

@joshcanhelp joshcanhelp force-pushed the change-state-and-nonce-handling branch 3 times, most recently from 0112dd4 to 02dc5b5 Compare May 10, 2018 18:49
if ( $this->query_vars( 'error' ) || $this->query_vars( 'error_description' ) ) {
$error_msg = sanitize_text_field( rawurldecode( $_REQUEST[ 'error_description' ] ) );
$error_code = sanitize_text_field( rawurldecode( $_REQUEST[ 'error' ] ) );
if ( ! empty( $_REQUEST['error'] ) || ! empty( $_REQUEST['error_description'] ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

would an error_description by itself be valid? I guess only when error is present. So 2nd clause could be removed.

$this->die_on_login( $error_msg, $error_code );
}

// Check for valid state nonce, set in WP_Auth0_Lock10_Options::get_state_obj().
// See https://auth0.com/docs/protocols/oauth2/oauth-state for more info.
if ( ! $this->validate_state() ) {
$state_returned = isset( $_REQUEST['state'] ) ? rawurldecode( $_REQUEST['state'] ) : null;
if ( ! $state_returned || ! WP_Auth0_State_Handler::get_instance()->validate( $state_returned ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

! $state_returned is already covered inside the verify method

} else {
// No cookie, need to create one.
$this->_uniqid = $this->generate_nonce();
Copy link
Contributor

Choose a reason for hiding this comment

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

don't you need to set the generated value to $_COOKIE?

* @return bool
*/
public function set_cookie() {
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this be called internally after generating a new nonce? (private). It doesn't receive any param so I don't see the point of it being public at all

@joshcanhelp joshcanhelp force-pushed the change-state-and-nonce-handling branch 3 times, most recently from 9912d9d to 81f15f4 Compare May 10, 2018 20:34
Copy link
Contributor

@lbalmaceda lbalmaceda left a comment

Choose a reason for hiding this comment

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

LGTM

@joshcanhelp joshcanhelp merged commit 014529c into dev May 10, 2018
@joshcanhelp joshcanhelp deleted the change-state-and-nonce-handling branch May 10, 2018 22:01
@joshcanhelp joshcanhelp mentioned this pull request Jun 5, 2018
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants