Proposal: REST API Authentication / Application Passwords

Problem statement: no way to authenticate third-party access to REST APIREST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/.

Ever since the REST API infrastructure merged via #33982 and shipped in WordPress 4.4 in December 2015, it’s been gaining momentum and been used in more and more places—throughout WordPress’s adminadmin (and super admin), via plugins and themes, and enabled deep, robust interactions powering new functionality such as the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editor.

However, the functionality has been limited in that the only way to make authenticated requests to the APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. in coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. has been through Cookie & Nonce-based authentication—there is no good way for third-party applications to communicate with WordPress in an authenticated fashion, apart from the legacy XML-RPC API.

This has resulted in frustration for our Mobile teams especially as they’re working to integrate Gutenberg support, which relies on the REST API. After some time having to store username/password to spoof a cookie and interactive session to scrape a nonce from the wp-admin DOM, and then to use an endpoint to get it instead via [46253]. All of which is a tremendously messy and awkward usage that completely falls apart if someone uses a variant of a two-factor authentication system.

Spoofing an interactive session just to make API requests is bad form and needlessly complex.

We’d like to propose integrating Application Passwords into Core.

There have been many systems considered, including everything from multiple incarnations of OAuth, JWT, and even some solutions that are combinations of the two. Some called for a centralized app repository, some had open registration, but all were complex and none of them could build sufficient traction to come to fruition.

Broad conceptual overview of varying methods (See: WP-API/authentication#15)

A simpler alternative to Application Passwords is pure Basic Authentication and detailed in #42790. However, Application Passwords is more comprehensive, and a far superior of a choice for the reasons that follow.

Benefit: Ease of API Requests

Given a login and an application password, making an API request is as simple as

curl --user "USERNAME:APPLICATION_PASSWORD" -X POST -d "title=New Title" https://my.wordpress.site/wp-json/wp/v2/posts/POST_ID

It uses the standard HTTPHTTP HTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands. authorization headers. Everything supports this trivially.

Benefit: Ease of Revoking Credentials

Application Passwords makes it easy to revoke any individual application password, or wholesale void all of a user’s application passwords. Application Passwords also lists the date a password was last used and the IP it was used from to help track down inactive credentials or bad actors using them from unexpected locations.

Benefit: Ease of Requesting API Credentials

While it is possible for a user to go to their user profile page and generate a new application password, for example if they are creating a command line tool for themselves, the ideal workflow looks something like this:

To request a password for your application, redirect users to:

https://example.com/wp-admin/authorize-application.php

The URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org is included in the REST API index to facilitate automated discovery.

{
  "name": "Trunk",
  "authentication": {
    "application-passwords": {
      "endpoints": {
        "authorization": "http://example.com/wp-admin/authorize-application.php"
      }
    }
  }
}

and use the following GET request parameters to specify:

  • app_name (required) – The human readable identifier for your app. This will be the name of the generated application password, so structure it like … “WordPress Mobile App on iPhone 12” for uniqueness between multiple versions. If omitted, the user will be required to provide an application name.
  • success_url (recommended) – The URL that you’d like the user to be sent to if they approve the connection. Two GET variables will be appended when they are passed back (user_login and password); these credentials can then be used for API calls. If the success_url variable is omitted, a password will be generated and displayed to the user, to manually enter into your application.
  • reject_url (optional) – If included, the user will get sent there if they reject the connection. If omitted, the user will be sent to the success_url, with ?success=false appended to the end. If the success_url is omitted, the user will be sent to their WordPress dashboard.

If the user is logged out, they’ll be redirected to the WordPress Login page. After logging in, they’ll be immediately redirected back to the Authorize Application screen.

In discussions with @timothyblynjacobs we’re unsure about whether to add a state parameter (which is just stored and passed back to the application to prevent CSRF attacks). Realistically apps could just include it on their own in the success_url or a site_url parameter (which could remind the application what site the returned credentials are for). Requiring apps to pass a state parameter could encourage best practices, but we wouldn’t be able to enforce that they validate its contents.

It’s also worth noting that the success_url and reject_url are both explicitly designed that apps can pass in custom protocols for the return URLs. That is, they could set them to be wordpress://authentication so that the user’s phone automatically redirects them back from their web browser, directly into the application with the credentials appended to the query. You may have seen this previously with other applications where you “Login with Facebook” in your browser and then Facebook sends you directly back into your app. Or with how your web browser can open Zoom directly on your laptop, pre-populating the room ID and password.

Benefit: Login Security

Unlike pure basic auth that requires entering in credentials directly into the application, Application Passwords allows for an interactive authentication flow. This means that login security features like Two Factor or reCAPTCHA can continue to protect user accounts.

One of the reasons XML-RPC is so often recommended to be disabled is that it allows brute forcing user’s passwords since those additional security protections can’t be implemented. A risk of implementing pure basic auth is that sites will be forced to disable it because it can’t be interactive.

Proposed solution: merge Application Passwords to core

While there is a standalone plugin for Application Passwords that’s developed in a GitHub repo, PR#540 to WordPress-develop is the official work we’re proposing to be merged into core. The pull request is based off of the original feature pluginFeature Plugin A plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins.’s codebase. We welcome comments on this proposal post, contributions to Application Passwords itself, and even more so review and feedback on the existing merge proposal pull request.

Props to @timothyblynjacobs for help on the content of this post, @jeffpaul for help on the structure of this post, and the many many people who have contributed to the analysis behind this proposal and to Application Passwords.

#application-passwords, #authentication, #rest-api, #two-factor