Skip to content

Commit

Permalink
Require and display the client_uri for dynamic clients.
Browse files Browse the repository at this point in the history
Fixes #20.
  • Loading branch information
TimothyBJacobs committed May 21, 2020
1 parent 3e56e77 commit 43be705
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 5 deletions.
18 changes: 17 additions & 1 deletion inc/admin/class-listtable.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace WP\OAuth2\Admin;

use WP\OAuth2\Client;
use WP\OAuth2\DynamicClient;
use WP_List_Table;
use WP_Query;

Expand Down Expand Up @@ -141,6 +142,21 @@ protected function column_name( $item ) {
* @return string Content of the column.
*/
protected function column_description( $item ) {
return $item->post_content;
$statement = get_post_meta( $item->ID, DynamicClient::SOFTWARE_STATEMENT_KEY, true );
$description = $item->post_content;

if ( $statement ) {
if ( $description ) {
$description .= '<br>';
}

$description .= sprintf(
/* translators: 1. The client URI. */
esc_html__( 'Application by %s.', 'oauth2' ),
sprintf( '<a href="%1$s" target="_blank" rel="noopener noreferrer"><code>%1$s</code></a>', esc_url( $statement->client_uri ) )
);
}

return $description;
}
}
17 changes: 17 additions & 0 deletions inc/admin/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace WP\OAuth2\Admin;

use WP\OAuth2\Client;
use WP\OAuth2\DynamicClient;
use WP_Error;

const BASE_SLUG = 'rest-oauth2-apps';
Expand Down Expand Up @@ -331,6 +332,8 @@ function render_edit_page() {
if ( is_array( $data['callback'] ) ) {
$data['callback'] = implode( ',', $data['callback'] );
}

$data['software_statement'] = get_post_meta( $consumer->get_post_id(), DynamicClient::SOFTWARE_STATEMENT_KEY, true );
}

// Header time!
Expand Down Expand Up @@ -374,6 +377,20 @@ function render_edit_page() {
<textarea class="regular-text" name="description" id="oauth-description" cols="30" rows="5" style="width: 500px"><?php echo esc_textarea( $data['description'] ); ?></textarea>
</td>
</tr>
<?php if ( ! empty( $data['software_statement'] ) ): ?>
<tr>
<th scope="row">
<?php echo esc_html_x( 'Dynamic Client', 'field name', 'oauth2' ); ?>
</th>
<td>
<?php printf(
/* translators: 1. The client URI */
esc_html__( 'Application by %s.', 'oauth2' ),
sprintf( '<a href="%1$s" target="_blank" rel="noopener noreferrer"><code>%1$s</code></a>', esc_url( $data['software_statement']->client_uri ) )
); ?>
</td>
</tr>
<?php endif; ?>
<tr>
<th scope="row">
<?php echo esc_html_x( 'Type', 'field name', 'oauth2' ); ?>
Expand Down
22 changes: 20 additions & 2 deletions inc/class-command.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class Command {
*
* ## OPTIONS
*
* <client_uri>
* : The base URI of your application.
*
* [<software_id>]
* : The software ID to use. Leave blank to generate one.
*
Expand All @@ -27,25 +30,40 @@ class Command {
* --redirect_uri=<redirect_uri>
* : The URI users will be redirected to after connecting.
*
* [--<field>=<value>]
* : Additional claims.
*
* @subcommand create-software-statement
*/
public function create_software_statement( $args, $assoc_args ) {
if ( empty( $args[0] ) ) {
$client_uri = $args[0];

if ( empty( $args[1] ) ) {
$software_id = wp_generate_uuid4();
\WP_CLI::log( 'Generated software id: ' . $software_id );
} else {
$software_id = $args[0];
$software_id = $args[1];
}

$name = get_flag_value( $assoc_args, 'client_name' );
$redirect_uri = get_flag_value( $assoc_args, 'redirect_uri' );

$statement = array(
'client_uri' => $client_uri,
'software_id' => $software_id,
'redirect_uris' => array( $redirect_uri ),
'client_name' => $name,
);

unset( $assoc_args['client_name'], $assoc_args['redirect_uri'] );
$statement = array_merge( $assoc_args, $statement );

$valid = DynamicClient::validate_statement( (object) $statement );

if ( is_wp_error( $valid ) ) {
\WP_CLI::error( $valid );
}

$signed = JWT::encode( $statement, '', 'none' );

if ( is_wp_error( $signed ) ) {
Expand Down
45 changes: 43 additions & 2 deletions inc/class-dynamicclient.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ class DynamicClient implements ClientInterface {
'minLength' => 1,
'maxLength' => 255,
),
'client_uri' => array(
'type' => 'string',
'format' => 'uri',
'required' => true,
),
'redirect_uris' => array(
'type' => 'array',
'items' => array(
Expand All @@ -46,7 +51,7 @@ class DynamicClient implements ClientInterface {
'required' => true,
'maxItems' => 1,
'minItems' => 1,
)
),
)
);

Expand Down Expand Up @@ -74,7 +79,7 @@ protected function __construct( $statement ) {
*/
public static function from_jwt( $jwt ) {
$statement = JWT::decode( $jwt, '', array( 'none' ), 'unsecure' );
$valid = rest_validate_value_from_schema( $statement, self::SCHEMA );
$valid = static::validate_statement( $statement );

if ( is_wp_error( $valid ) ) {
return $valid;
Expand All @@ -83,6 +88,33 @@ public static function from_jwt( $jwt ) {
return new static( $statement );
}

/**
* Validates the software statement.
*
* @param \stdClass $statement
*
* @return WP_Error|true
*/
public static function validate_statement( $statement ) {
$valid = rest_validate_value_from_schema( $statement, self::SCHEMA, 'statement' );

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

$client_host = parse_url( $statement->client_uri, PHP_URL_HOST );

foreach ( $statement->redirect_uris as $redirect_uri ) {
$redirect_host = parse_url( $redirect_uri, PHP_URL_HOST );

if ( ! $redirect_host || $redirect_host !== $client_host ) {
return new WP_Error( 'client_uri_mismatch', __( 'The redirect URI is not on the same domain as the client URI.', 'oauth2' ) );
}
}

return true;
}

public function get_id() {
return $this->statement->software_id;
}
Expand Down Expand Up @@ -192,6 +224,15 @@ public function approve() {
return $persisted->approve();
}

/**
* Get's the software statement.
*
* @return \stdClass
*/
public function get_software_statement() {
return $this->statement;
}

/**
* Persists a dynamic client to a real client.
*
Expand Down
5 changes: 5 additions & 0 deletions inc/types/class-base.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public function handle_authorisation() {
$state = isset( $_GET['state'] ) ? sanitize_text_field( wp_unslash( $_GET['state'] ) ) : null;

$client = get_client( $client_id );

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

if ( empty( $client ) ) {
return new WP_Error(
'oauth2.types.authorization_code.handle_authorisation.invalid_client_id',
Expand Down
21 changes: 21 additions & 0 deletions theme/oauth2-authorize.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,19 @@

<style>

#login {
width: 60vw;
max-width: 650px;
}

.login-title {
margin-bottom: 15px;
}

#login form p.client-description {
margin-bottom: 15px;
}

.login-info .avatar {
margin-right: 15px;
margin-bottom: 15px;
Expand Down Expand Up @@ -73,6 +82,18 @@
)
)
);

if ( $client instanceof \WP\OAuth2\DynamicClient ) {
printf(
'<p class="client-description">%s</p>',
sprintf(
/* translators: %1$s: client name. %2$s: the app URI. */
__( '%1$s is an application by %2$s.', 'oauth2' ),
esc_html( $client->get_name() ),
sprintf( '<a href="%1$s" target="_blank" rel="noopener noreferrer"><code>%1$s</code></a>', esc_url( $client->get_software_statement()->client_uri ) )
)
);
}
?>

<div class="login-info">
Expand Down

0 comments on commit 43be705

Please sign in to comment.