Skip to content

Instantly share code, notes, and snippets.

@ouija
Last active December 9, 2019 08:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ouija/0d111feed63bfaa118a0d3ecd20666d0 to your computer and use it in GitHub Desktop.
Save ouija/0d111feed63bfaa118a0d3ecd20666d0 to your computer and use it in GitHub Desktop.
WP API SwaggerUI with WooCommerce Consumer Key/Secret Authentication
<?php
class SwaggerAuth {
private $error = null;
// woocommerce/includes/class-wc-rest-authentication.php -> get_user_data_by_consumer_key function
private function get_user_data_by_consumer_key( $consumer_key ) {
global $wpdb;
$consumer_key = wc_api_hash( sanitize_text_field( $consumer_key ) );
$user = $wpdb->get_row(
$wpdb->prepare(
"
SELECT key_id, user_id, permissions, consumer_key, consumer_secret, nonces
FROM {$wpdb->prefix}woocommerce_api_keys
WHERE consumer_key = %s
",
$consumer_key
)
);
return $user;
}
public function handler( $user_id ) {
// Don't authenticate twice
if ( ! empty( $user_id ) ) {
return $user_id;
}
$server = new SwaggerBag( $_SERVER );
// Check if consumer_key/secret get variables are being passed and use those to authenticate
if ( ! empty( $_GET['consumer_key'] ) && ! empty( $_GET['consumer_secret'] ) ) {
$server->set( 'PHP_AUTH_USER', $_GET['consumer_key'] );
$server->set( 'PHP_AUTH_PW', $_GET['consumer_secret'] );
}
// Check that we're trying to authenticate
if ( ! $server->has( 'PHP_AUTH_USER' ) ) {
$user_pass = $server->get( 'REDIRECT_HTTP_AUTHORIZATION' );
if ( $server->has( 'REDIRECT_HTTP_AUTHORIZATION' ) && ! empty( $user_pass ) ) {
list($username, $password) = explode( ':', base64_decode( substr( $user_pass, 6 ) ) );
$server->set( 'PHP_AUTH_USER', $username );
$server->set( 'PHP_AUTH_PW', $password );
} else {
return $user_id;
}
}
$username = $server->get( 'PHP_AUTH_USER' );
$password = $server->get( 'PHP_AUTH_PW' );
/**
* In multi-site, wp_authenticate_spam_check filter is run on authentication. This filter calls
* get_currentuserinfo which in turn calls the determine_current_user filter. This leads to infinite
* recursion and a stack overflow unless the current function is removed from the determine_current_user
* filter during authentication.
*/
remove_filter( 'determine_current_user', [ $this, 'handler' ], 14 );
$user = wp_authenticate( $username, $password );
add_filter( 'determine_current_user', [ $this, 'handler' ], 14 );
if ( is_wp_error( $user ) ) {
if (class_exists( 'woocommerce' )) {
$this->user = $this->get_user_data_by_consumer_key( $username );
if ( !empty( $this->user ) && hash_equals( $this->user->consumer_secret, $password ) ) {
$this->error = true;
return $this->user->user_id;
}
} else {
$this->error = $user;
return null;
}
}
$this->error = true;
return $user->ID;
}
public function error( $error ) {
if ( ! empty( $error ) ) {
return $error;
}
return $this->error;
}
public function appendSwaggerAuth( $auth ) {
if ( ! is_array( $auth ) ) {
$auth = [];
}
$auth['basic'] = array(
'type' => 'basic'
);
return $auth;
}
}
$basic = new SwaggerAuth();
add_filter( 'determine_current_user', [ $basic, 'handler' ], 14 );
add_filter( 'rest_authentication_errors', [ $basic, 'error' ] );
add_filter( 'swagger_api_security_definitions', [ $basic, 'appendSwaggerAuth' ] );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment