Skip to content

Commit

Permalink
Merge pull request #258 from dshanske/dec1fixes
Browse files Browse the repository at this point in the history
Add Validation Functions and Fix CSS
  • Loading branch information
dshanske authored Dec 2, 2023
2 parents e7813d9 + c7cebe1 commit 7bf0ee1
Show file tree
Hide file tree
Showing 14 changed files with 468 additions and 354 deletions.
16 changes: 8 additions & 8 deletions includes/class-indieauth-authorization-endpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function register_routes() {
),
// The Client URL.
'client_id' => array(
'validate_callback' => 'rest_is_valid_url',
'validate_callback' => 'indieauth_validate_client_identifier',
'sanitize_callback' => 'esc_url_raw',
'required' => true,
),
Expand Down Expand Up @@ -113,7 +113,7 @@ public function register_routes() {
/* The Profile URL the user entered. Optional.
*/
'me' => array(
'validate_callback' => 'rest_is_valid_url',
'validate_callback' => 'indieauth_validate_user_identifier',
'sanitize_callback' => 'esc_url_raw',
),
),
Expand All @@ -135,7 +135,7 @@ public function register_routes() {
/* The client's URL, which MUST match the client_id used in the authentication request.
*/
'client_id' => array(
'validate_callback' => 'rest_is_valid_url',
'validate_callback' => 'indieauth_validate_client_identifier',
'sanitize_callback' => 'esc_url_raw',
),
/* The client's redirect URL, which MUST match the initial authentication request.
Expand Down Expand Up @@ -365,11 +365,11 @@ public function authorization_code( $params ) {
}
}

$code = $params['code'];
$code_verifier = isset( $params['code_verifier'] ) ? $params['code_verifier'] : null;
$params = wp_array_slice_assoc( $params, array( 'client_id', 'redirect_uri' ) );
$token = $this->get_code( $code );
$scopes = isset( $token['scope'] ) ? array_filter( explode( ' ', $token['scope'] ) ) : array();
$code = $params['code'];
$code_verifier = isset( $params['code_verifier'] ) ? $params['code_verifier'] : null;
$params = wp_array_slice_assoc( $params, array( 'client_id', 'redirect_uri' ) );
$token = $this->get_code( $code );
$scopes = isset( $token['scope'] ) ? array_filter( explode( ' ', $token['scope'] ) ) : array();

if ( ! $token ) {
return new WP_OAuth_Response( 'invalid_grant', __( 'Invalid authorization code', 'indieauth' ), 400 );
Expand Down
23 changes: 22 additions & 1 deletion includes/class-indieauth-client-discovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ public function __construct( $client_id ) {
}

private function fetch( $url ) {

// Validate if this is an IP address
$ip = filter_var( wp_parse_url( $url, PHP_URL_HOST ), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 );
$donotfetch = array(
'127.0.0.1',
'0000:0000:0000:0000:0000:0000:0000:0001',
'::1',
);

// If this is an IP address ion the donotfetch list then do not fetch.
if ( $ip && ! in_array( $ip, $donotfetch ) ) {
return new WP_Error( 'do_not_fetch', __( 'Client Identifier is localhost', 'indieauth' ) );
}

$wp_version = get_bloginfo( 'version' );
$user_agent = apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) );
$args = array(
Expand All @@ -38,7 +52,14 @@ private function fetch( $url ) {
'redirection' => 3,
'user-agent' => "$user_agent; IndieAuth Client Information Discovery",
);
return wp_safe_remote_get( $url, $args );
$response = wp_safe_remote_get( $url, $args );
if ( ! is_wp_error( $response ) ) {
$code = wp_remote_retrieve_response_code( $response );
if ( ( $code / 100 ) !== 2 ) {
return new WP_Error( 'retrieval_error', __( 'Failed to Retrieve Client Details', 'indieauth' ), $code );
}
}
return $response;
}

private function parse( $url ) {
Expand Down
2 changes: 1 addition & 1 deletion includes/class-indieauth-token-endpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function register_routes() {
/* The client's URL, which MUST match the client_id used in the authentication request.
*/
'client_id' => array(
'validate_callback' => 'rest_is_valid_url',
'validate_callback' => 'indieauth_validate_client_identifier',
'sanitize_callback' => 'esc_url_raw',
),
/* The client's redirect URL, which MUST match the initial authentication request.
Expand Down
123 changes: 27 additions & 96 deletions includes/class-web-signin.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ public function __construct() {
add_action( 'init', array( $this, 'settings' ) );

add_action( 'login_form', array( $this, 'login_form' ) );
add_filter( 'login_form_defaults', array( $this, 'login_form_defaults' ), 10, 1 );
add_filter( 'gettext', array( $this, 'register_text' ), 10, 3 );
add_action( 'login_form_websignin', array( $this, 'login_form_websignin' ) );

add_action( 'authenticate', array( $this, 'authenticate' ), 20, 2 );
add_action( 'authenticate', array( $this, 'authenticate_url_password' ), 10, 3 );
}

public function settings() {
Expand All @@ -37,9 +34,27 @@ public function settings() {
* @param string $redirect_uri where to redirect
*/
public function websignin_redirect( $me, $redirect_uri ) {
$me = indieauth_validate_user_identifier( $me );
if ( ! $me ) {
return new WP_Error(
'authentication_failed',
__( '<strong>ERROR</strong>: Invalid URL', 'indieauth' ),
array(
'status' => 401,
)
);
}
$endpoints = find_rels( $me, array( 'indieauth-metadata', 'authorization_endpoint' ) );

if ( array_key_exists( 'indieauth-metadata', $endpoints ) ) {
if ( ! $endpoints ) {
return new WP_Error(
'authentication_failed',
__( '<strong>ERROR</strong>: Could not discover endpoints', 'indieauth' ),
array(
'status' => 401,
)
);
} elseif ( array_key_exists( 'indieauth-metadata', $endpoints ) ) {
$state = $this->get_indieauth_metadata( $endpoints['indieauth-metadata'] );
} elseif ( ! array_key_exists( 'authorization_endpoint', $endpoints ) ) {
return new WP_Error(
Expand Down Expand Up @@ -175,6 +190,9 @@ public function authenticate( $user, $url ) {
}
if ( array_key_exists( 'iss', $_REQUEST ) ) {
$iss = rawurldecode( $_REQUEST['iss'] );
if ( ! indieauth_validate_issuer_identifier( $iss ) ) {
return new WP_Error( 'indieauth_iss_error', __( 'Issuer Parameter is Not Valid', 'indieauth' ) );
}
if ( $iss !== $state['issuer'] ) {
return new WP_Error( 'indieauth_iss_error', __( 'Issuer Parameter does not Match Server Metadata', 'indieauth' ) );
}
Expand Down Expand Up @@ -208,73 +226,6 @@ public function authenticate( $user, $url ) {
}



/**
* Authenticate user to WordPress using URL and Password
*/
public function authenticate_url_password( $user, $url, $password ) {
if ( $user instanceof WP_User ) {
return $user;
}
if ( empty( $url ) || empty( $password ) ) {
if ( is_wp_error( $user ) ) {
return $user;
}
if ( is_oauth_error( $user ) ) {
return $user->to_wp_error();
}
$error = new WP_Error();

if ( empty( $url ) ) {
$error->add( 'empty_username', __( '<strong>ERROR</strong>: The URL field is empty.', 'indieauth' ) ); // Uses 'empty_username' for back-compat with wp_signon()
}

if ( empty( $password ) ) {
$error->add( 'empty_password', __( '<strong>ERROR</strong>: The password field is empty.', 'indieauth' ) );
}

return $error;
}

if ( ! wp_http_validate_url( $url ) ) {
return $user;
}
$user = get_user_by_identifier( $url );

if ( ! $user ) {
return new WP_Error(
'invalid_url',
__( '<strong>ERROR</strong>: Invalid URL.', 'indieauth' ) .
' <a href="' . wp_lostpassword_url() . '">' .
__( 'Lost your password?', 'indieauth' ) .
'</a>'
);
}

/** This filter is documented in wp-includes/user.php */
$user = apply_filters( 'wp_authenticate_user', $user, $password );

if ( is_wp_error( $user ) ) {
return $user;
}

if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
'incorrect_password',
sprintf(
/* translators: %s: url */
__( '<strong>ERROR</strong>: The password you entered for the URL %s is incorrect.', 'indieauth' ),
'<strong>' . $url . '</strong>'
) .
' <a href="' . wp_lostpassword_url() . '">' .
__( 'Lost your password?', 'indieauth' ) .
'</a>'
);
}

return $user;
}

/**
* render the login form
*/
Expand All @@ -285,45 +236,25 @@ public function login_form() {
}
}

public function login_form_defaults( $defaults ) {
$defaults['label_username'] = __( 'Username, Email Address, or URL', 'indieauth' );
return $defaults;
}

public function register_text( $translated_text, $untranslated_text, $domain ) {
if ( 'Username or Email Address' === $untranslated_text ) {
$translated_text = __( 'Username, Email Address, or URL', 'indieauth' );
}
return $translated_text;
}

public function login_form_websignin() {
if ( 'GET' === $_SERVER['REQUEST_METHOD'] ) {
include plugin_dir_path( __DIR__ ) . 'templates/websignin-form.php';
}
$login_errors = null;
if ( 'POST' === $_SERVER['REQUEST_METHOD'] ) {
$redirect_to = array_key_exists( 'redirect_to', $_REQUEST ) ? $_REQUEST['redirect_to'] : '';
$redirect_to = rawurldecode( $redirect_to );

if ( array_key_exists( 'websignin_identifier', $_POST ) ) { // phpcs:ignore
$me = esc_url_raw( $_POST['websignin_identifier'] ); //phpcs:ignore
// Check for valid URLs
if ( ! wp_http_validate_url( $me ) ) {
return new WP_Error( 'websignin_invalid_url', __( 'Invalid User Profile URL', 'indieauth' ) );
}

$return = $this->websignin_redirect( $me, wp_login_url( $redirect_to ) );
if ( is_wp_error( $return ) ) {
echo '<div id="login_error">' . esc_html( $return->get_error_message() ) . "</div>\n";
return $return;
$login_errors = $return;
}
if ( is_oauth_error( $return ) ) {
$return = $return->to_wp_error();
echo '<div id="login_error">' . esc_html( $return->get_error_message() ) . "</div>\n";
return $return;
$login_errors = $return->to_wp_error();
}
}
}

include plugin_dir_path( __DIR__ ) . 'templates/websignin-form.php';
exit;
}
}
Expand Down
Loading

0 comments on commit 7bf0ee1

Please sign in to comment.