Application Passwords (Authorization)
In WordPress 5.6, a new system for creating authorized requests to various WordPress APIs, particularly the REST API, was introduced. This system is called — Application Passwords.
Simply put, application passwords are needed to allow an application to authenticate as a user of the site (with the same rights), without providing the actual account password. The password is created in the profile separately and is not stored in plain text in the database (it is stored as a hash). You can create as many such passwords as you want. Also, any of the created passwords can be revoked (deleted) at any moment.
The existing cookie-based authentication system is not going anywhere, and everything that worked on this basis will continue to work as before.
The logic of application passwords was taken from the Application Passwords plugin, so it is recommended to deactivate it after upgrading to WordPress 5.6. However, if you leave it active, the site should still work without errors. This plugin can be used for future prototyping.
Application Password Format
The length of the password is specified by the constant PW_LENGTH and is 24 characters. It is created by the function wp_generate_password(), which has the use of special characters disabled. Thus, the password can consist of characters: a-zA-Z0-9
- lowercase letters, uppercase letters, and numbers.
When output, the password is split into chunks of 4 characters, for example:
abcd EFGH 1234 ijkl MNOP 6789
Application passwords can be used with or without spaces. Spaces will simply be removed before the password is verified. Instead of spaces, you can also use the characters _
and -
.
abcd EFGH 1234 ijkl MNOP 6789 abcd_EFGH_1234_ijkl_MNOP_6789 abcd-EFGH-1234-ijkl-MNOP-6789
Thus, passwords are cleaned of extra characters (spaces, dashes) before comparison:
/* * Strip out anything non-alphanumeric. This is so passwords can be used with * or without spaces to indicate the groupings for readability. * * Generated application passwords are exclusively alphanumeric. */ $password = preg_replace( '/[^a-z\d]/i', '', $password );
Above we described the options that WordPress will understand. In your HTTP client, use the one it supports. For example, Postman will understand all options, while PhpStorm will understand all except the one with spaces.
Data Storage
The password hash will be stored as an array in the user's meta-field _application_passwords
, just as the login session is currently stored, see WP_Session_Tokens.
Example of the value of the meta-field _application_passwords
:
Array ( [0] => Array ( [uuid] => fbadcb50-4385-4701-96a6-9a4f07527d08 [app_id] => [name] => My Application [password] => $P$Bui9Czv.OEQ6ES6YYMWge8/e.qmWJP/ [created] => 1607599946 [last_used] => [last_ip] => ) )
As you can see, the data includes a unique password ID uuid, the application name, the password creation date, and the last usage data of the key.
The class WP_Application_Passwords contains all the necessary methods for saving and retrieving the password.
Creating an Application Password
Also read: Setting a pre-known application password.
There are 3 ways to create a password for an application.
Method 1: On the profile page in the WP admin panel
This block is only available if the site is running on https.
Here you can also see which passwords are in use and delete them if necessary.
When authenticating using a specific password, data will appear in the table indicating when and by whom it was used. These are the fields last_used
and last_ip
.
Data in these fields will be recorded once and will be updated after 24 hours upon repeated use of this password. This is a small performance optimization to avoid updating metadata every time a request is made.
Method 2: Special page in the admin panel /authorize-application.php
This method is designed for use by the application itself.
When a regular GET request is made to the root REST route /wp-json/
, the response in the authentication
field will contain data about the authentication methods. Since version WP 5.6, application-passwords authorization has appeared, which specifies a link that can be given to the site user. By following this link, the user authorizes your application (creating a password that the application can use to communicate with the site on behalf of the user).
{ "name": "wptest.dev", "description": "Another WordPress site", "url": "http://example.com/wp", "home": "https://example.com", "namespaces": [ "oembed/1.0", "wp/v2", "wp-site-health/v1" ], "authentication": { "application-passwords": { "endpoints": { "authorization": "https://example.com/wp/wp-admin/authorize-application.php" } } }, "routes": { ... } }
If such a link is not available, it is likely that the site does not use the HTTPS protocol or this feature has been intentionally disabled.
The JSON property value response.authentication['application-passwords'].endpoints.authorization
usually looks like this:
https://example.com/wp-admin/authorize-application.php
By following this link, you can also create another application password as described above.
However, if you are sent to such a link by the application, you can pass additional GET parameters to it. This way, you won't need to enter the application name and ID. The available GET parameters:
- app_name(string) (recommended to specify)
- The name of the application that is understandable to a person. This name will become the name of the created password (you will be able to orient yourself by it). For example:
WordPress Mobile App on iPhone 12
. - app_id(UUID) (recommended to specify)
- The application identifier in UUID format. This ID allows you to identify a specific application. This ID does not have special significance. You as a developer can use it to find all application passwords created for your application.
- success_url(string) (recommended to specify)
The URL to which the user will be redirected after the password is created. In this case, the specified URL will have 3 additional GET parameters added:
site_url
,user_login
,password
. You need to save this data in the application to authenticate via the API.If this parameter is not specified, when the password creation button is clicked, the user will not be redirected anywhere, and the created password will be shown to them. They will need to enter it into the application.
- reject_url(string)
The URL to which the user will be sent if they refuse to create a password.
If not specified, the user will be sent to
success_url
with the parameter?success=false
. If neithersuccess_url
norreject_url
is specified, the user will be redirected to the console.
Now let's consider an example of how this works.
Suppose we received the following link from the application (for clarity, I've moved the parameters to separate lines):
https://example.com/wp-admin/authorize-application.php ?app_name=My Site On Android &app_id=d2321b5c-edf0-4a3c-9223-4719f8e6b028 &success_url=https://example.com/auth-ok &reject_url=https://example.com/auth-error
Let's go to the link:
Now, when clicking "Yes, I allow...", a password will be created and the user will be redirected to the link
https://example.com/auth-ok ?site_url=https://example.com/wp &user_login=kama &password=GENERATED_PASS
It is not a problem if the user needs to log in to the site first. Since the parameters are passed through GET variables, all of them will fall into the parameter ?redirect=...
and after logging in to the site, the user will be able to continue the application authorization.
success_url
and reject_url
must use an https://
connection or application protocols myapp://
, otherwise the user will see such a message.
Here is an example of a simple javascript application (less than 100 lines of code) that uses it for authentication on a WordPress site. This is not the most neat code, it was created in a couple of hours, but it shows how to make authorized requests.
Method 3: REST API
POST request to the route /wp/v2/users/{id}/application-passwords
. For more details, see here.
Method 4: Function create_new_application_password()
See WP_Application_Passwords::create_new_application_password()
Using an Application Password
An application password will not work on the wp-login.php
page. It is created for programs, not for people.
REST API
The application password can be passed in the REST request over https://
via Basic authentication.
That is, you need to pass in the request headers the parameter Authorization
with the value Basic base64(login:app_password)
.
HTTP API authorization via Application Password
$response = wp_remote_request( 'http://example.com/wp-json/wp/v2/posts/113', [ 'method' => 'DELETE', 'headers' => [ 'Authorization' => 'Basic ' . base64_encode( 'login:abcd_EFGH_1234_ijkl_MNOP_6789' ) ] ] ); if( 200 == wp_remote_retrieve_response_code( $response ) ) echo 'Post deleted!'; else echo 'Error: Failed to delete post';
Also see: WP HTTP API
JavaScript authorization via Application Password
Such authorization is only needed if an AJAX request is sent from one site to another. If the AJAX request occurs within the site, and the user is already authenticated, authentication cookies will be sent along with the request, which means that authentication already exists, and you only need to specify a nonce code (see above).
Please note that such JS should be included on pages accessible only to admins; otherwise, anyone can open the js file and see the login and password.
$.ajax({ url: 'http://example.com/wp-json/wp/v2/posts/113', method: 'DELETE', crossDomain: true, beforeSend: function ( xhr ) { xhr.setRequestHeader( 'Authorization', 'Basic ' + Base64.encode( 'login:abcd_EFGH_1234_ijkl_MNOP_6789' ) ); }, success: function( data, txtStatus, xhr ) { console.log( data ); console.log( xhr.status ); } });
CLI authorization via Application Password
Update the description of user 12
curl -X PUT -d "description=User description" --user "login:aaaa ssss d3d3 f4f4 g5g5 h6h6" https://example.com/wp-json/wp/v2/users/12 | json_pp
Delete post 12
curl -X DELETE --user "login:aaaa ssss d3d3 f4f4 g5g5 h6h6" https://example.com/wp-json/wp/v2/posts/12 | json_pp
| json_pp
(JSON Pretty Print) is needed so that the JSON response is not in a single line.
XML-RPC API
To use the application password with the XML-RPC API, you can simply use it instead of the actual account password.
Example of a request from the command line. In it, you just need to replace the login, password, and hostname:
curl -H 'Content-Type: text/xml' -d '<methodCall><methodName>wp.getUsers</methodName><params><param><value>1</value></param><param><value>USERNAME</value></param><param><value>PASSWORD</value></param></params></methodCall>' https://HOSTNAME/xmlrpc.php
Other APIs
Authentication via application password can also be applied to future WordPress APIs. For example, if GraphQL is added to WordPress, application passwords will provide it with a well-established authentication logic that will work out of the box.
Example of checking if the current request is a request to any API for WPGraphQL. Now WPGraphQL will be able to accept authenticated requests without additional plugins, using only the functionality of application passwords.
Notes
By default, application passwords are available to all users on sites served over the SSL/HTTPS protocol. Access can be changed using the filters wp_is_application_passwords_available and wp_is_application_passwords_available_for_user.
For example, to completely disable application passwords, add the following code to functions.php:
add_filter( 'wp_is_application_passwords_available', '__return_false' );
Without SSL, an attacker will see the application password in an intercepted request between your site and the application. If you are comfortable with such a risk, you can completely disable the availability check for application passwords.
add_filter( 'wp_is_application_passwords_available', '__return_true' );
If desired, you can limit which users on your site can use the application password feature. For example, use the following code to allow application passwords only for administrators:
add_filter( 'wp_is_application_passwords_available_for_user', 'fix_app_password_availability', 10, 2 ); function fix_app_password_availability( $available, $user ){ if ( ! user_can( $user, 'manage_options' ) ) { $available = false; } return $available; }
Future Development
Scope of Access
In future versions, it is planned to include the ability to restrict access for specific passwords. For now, it is assumed that such functionality will be extended through plugins, which will then be added to the core.
More Appropriate Rights
Currently, user application passwords can be managed by any user who has the edit_user
capability. The ability to adjust this behavior with a new set of more granular capabilities is scheduled for WP 5.7](https://core.trac.wordpress.org/ticket/51703).
Two-Factor Authentication
The introduced application passwords eliminate barriers to enabling multi-factor authentication.
Previously, when enabling another authentication factor on the wp-login.php
login page, there was no way to implement the same authorization on the deprecated XML-RPC system. This functionality would have to be abandoned. But now, with another option to use various APIs, there is also the opportunity to develop basic authorization through wp-login.php
.
Related Functions
All functions see here.
wp_authenticate_application_password() | Authenticates the user using an application password. |
wp_is_application_passwords_available() | Checks if Application Passwords is globally available. |
--
Related Links: