Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This is an example client app to integrate with the WordPress 5.6 Application Passwords system. It walks the user through authenticating, and then queries and enumerates all users on the site.
(function($){
const $root = $( '#root' );
const $stage1 = $( '.stage-1', $root );
const $stage2 = $( '.stage-2', $root );
// If there's no GET string, then no credentials have been passed back. Let's get them.
if ( ! window.location.href.includes('?') ) {
// Stage 1: Get the WordPress Site URL, Validate the REST API, and Send to the Authentication Flow
const $urlInput = $( 'input[type=url]', $stage1 );
$('input[type=submit]', $stage1).click(function(event){
event.preventDefault();
if ( $urlInput[0].validity.valid ) {
let linky = $urlInput.val() + '?rest_route=/';
$stage1.append( '<p>Attempting to query <a href="' + linky + '">' + linky + '</a>…</p>' );
$.getJSON( linky, function( data ) {
// If it doesn't look like a WordPress REST API response, bail!
if ( ! data.url ) {
$stage1.append( '<p>Error: ' + linky + ' does not seem to be a WordPress REST API.</p>' );
return;
}
console.log( data );
// Yay, we found WordPress! Report back to the user.
$stage1.append( '<p>Success: Found <strong>' + data['name'] + '</strong>' +
( data.description ? ': <em>' + data.description + '</em></p>' : '</p>' ) );
// If no Application Passwords, bail.
if ( ! data.authentication['application-passwords'] ) {
$stage1.append('<p>Looks like Application Passwords is not available!</p>');
$urlInput.focus();
return;
}
// Yay we have Application Passwords!
const authorizationLinky = data.authentication['application-passwords'].endpoints.authorization +
'?' + $.param( {
app_name: 'Test Application',
// We're appending `site_url` here until core passes the siteurl back with it.
success_url: location.href + '?site_url=' + linky.split('?')[0]
} );
// Display the link for the user to authenticate.
$stage1.append( '<p>Would you like to <a href="' + authorizationLinky + '">authenticate with that site</a>?</p>' );
} );
} else {
$stage1.append( '<p>Error: ' + $urlInput.val() + ' does not seem to validate as a url.</p>') ;
}
});
} else {
$stage1.hide();
const credentials = new URLSearchParams( window.location.href.split('?')[1] );
$stage2.append( '<p>Got credentials! user: <kbd>' + credentials.get('user_login') + '</kbd>' +
' pass: <kbd>' + credentials.get('password') + '</kbd></p>' );
const api_root = credentials.get('site_url') + '?rest_route=/';
$stage2.append( '<p>Making authenticated request to site to list users…</p>' );
// using & instead of ? as we're already using the rest_route get arg.
$.ajax( api_root + 'wp/v2/users&context=edit', {
crossDomain: true,
headers: {
"Authorization": "Basic " + btoa( credentials.get('user_login') + ":" + credentials.get('password') )
},
success: function( data ) {
$stage2.append( '<p>Found ' + data.length + ' user(s):</p>' );
$.each( data, function( index, user ) {
$stage2.append( '<p>User ID ' + user.id + ': "' + user.username + '" &lt;' + user.email + '&gt;</p>' );
});
}
});
}
})(jQuery);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<title>WordPress REST API / Application Password Client</title>
</head>
<body>
<div id="root">
<form class="stage-1">
<input type="url" name="wordpressUrl" placeholder="WordPress URL…" />
<input type="submit" value="Go »" />
</form>
<div class="stage-2"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="./client.js"></script>
</body>
</html>
@georgestephanis

This comment has been minimized.

Copy link
Owner Author

@georgestephanis georgestephanis commented Oct 22, 2020

Yes a lot of my JS is sloppy on this. It was a late night two hour coding binge. I claim no style points.

But it works.

@grefel

This comment has been minimized.

Copy link

@grefel grefel commented Jan 25, 2021

Thanks for sharing!

This code only works if you are not logged into the target WordPress with the same user. -> That means log out after you allow the Test Application.

Reason: If a cookie is sent in the request header, Basic Authentication will not work. The alternative is to run your client.js from a different URL.
@georgestephanis Is this intentional?

@ivanjeremic

This comment has been minimized.

Copy link

@ivanjeremic ivanjeremic commented Feb 11, 2021

ajax? 2021

@swashata

This comment has been minimized.

Copy link

@swashata swashata commented Jul 10, 2021

Thank you very much.

@maheshwaghmare

This comment has been minimized.

Copy link

@maheshwaghmare maheshwaghmare commented Jul 11, 2021

It's quicker implementation with jQuery and $.ajax for demonstration.

We'll use fetch() or any other library instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment