Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application Passwords #13

Open
georgestephanis opened this issue Mar 24, 2020 · 5 comments
Open

Application Passwords #13

georgestephanis opened this issue Mar 24, 2020 · 5 comments

Comments

@georgestephanis
Copy link

georgestephanis commented Mar 24, 2020

Repo: https://github.com/wordpress/application-passwords

@TimothyBJacobs asked me to write up an issue about the work already done on Application Passwords, so here we go:

User Flow : New App

The flow is as simple as an app linking to your.site/wp-admin/?path=auth_app with a number of optional get strings appended to it. This ensures that if the user isn't already logged in, the request arguments get preserved through the authentication flow:

  • 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 dashboard.

The UI looks something like this:

4350f5c8-ff2f-11e6-9399-8bbbe3fb44b5

and when the user completes the flow, they can be redirected back to the url they came from, or even directly back into the app requesting authorization via custom app protocols.

The flow is accomplished and made smoother via javascript / ajax requests, however will operate just fine via traditional form submissions if JS is disabled in the browser for any reason.

Managing existing app passwords

The user profile page panel for managing application passwords looks like this:

434fcd60-ff2f-11e6-938f-5a49609fff4b

It can be used to generate new passwords directly, but for auth requests from an external website or app it's much better ux to use the previous flow.

The table is managed and updated via jQuery for dom queries/insertions/deletions, and wp.template for generating the markup. It should be trivially rewritable into React if there's a need to expand React usage in the admin.

Data

The generated application passwords are 24 characters long to ensure over 128 bits of entropy (we're actually at over 142 bits of entropy -- 62^24), and have their hashes stored in usermeta under the _application_passwords key.

Application Passwords are stored in the database as an array of arrays under the aforementioned key.

Each entry consists of the following properties:

  • name -- The designated application name given when the password was created. Not guaranteed to be unique.
  • password -- The password's hash, via wp_hash_password()
  • created -- The time() that the password was created.
  • last_used -- The time() that the password was used most recently. Can be useful for finding and clearing out old passwords no longer in use.
  • last_ip -- The $_SERVER['REMOTE_ADDR'] that most recently used the application password. This can be a very useful audit trail to identify if it has been used improperly.

Authentication

Application Passwords explicitly only work for REST API or XML-RPC authentication. They can not be used and will not function when attempting an interactive login via wp-login.php or the like.

REST API Support

The existing application-passwords plugin fully supports the REST API, offering endpoints to list, add new application passwords, and delete one or all application passwords for a given user.

https://github.com/WordPress/application-passwords/blob/0e71ecdad32eb54c7bfebac0553482e72f3134aa/class.application-passwords.php#L73-L293

DON'T PANIC

The application-passwords repository has a lot of random files in it. Most of these were added for automated testing and such and can be ignored. The only relevant files in it to understand what's going on are:

  • application-passwords.css -- general styles
  • application-passwords.js -- js for the profile page listing ui
  • application-passwords.php -- basic plugin loader -- just loads the class and kicks it off
  • auth-app.js -- js for the auth flow ui
  • class.application-passwords-list-table.php -- list table for the profile page -- minimal
  • class.application-passwords.php -- most of the hard work. well commented, phpdoc, etc.

In Summation

Some of the most relevant wins I see here with Application Passwords are:

  • Application Passwords can only be used for API requests, never for getting a full wp-admin login.
  • Doesn't require password storage. Applications integrating with WordPress never see the user's actual password.
  • Application Passwords are high-entropy, and fully revokable.
  • Very easy implementation. No libraries needed, as the username and password can be passed via standard basic auth (as supported by curl already). Handles FastCGI incompatability by using .htaccess to rewrite to a different authentication header, and then catches via a fallback.
  • Backward Compatible with XML-RPC! The generated credentials can be used as a drop in replacement for legacy apps that use XML-RPC, and also enables apps doing new integrations to query legacy XML-RPC endpoints if needed for any reason.
@georgestephanis
Copy link
Author

This could also easily use the code I'd written for

https://github.com/WordPress/wordpress-develop/pull/169/files#diff-a32e81b26e79371567b4b1824bc2a427R298-R304

instead, and just let apps send the Basic ******** string versus the WP_Authorization header instead of Authorization, sidestepping the fastcgi issue completely with no htaccess tweaks.

@DanielRuf
Copy link

I think there should be some hint about the domain at earliest as possible.
For example My application (example.com).

This would make such cases more clear like described in the following:
https://youtu.be/MgDbnvuJmPc?t=825
https://youtu.be/MgDbnvuJmPc?t=845

source: https://www.wordfence.com/blog/2020/12/wordpress-5-6-introduces-a-new-risk-to-your-site-what-to-do/

@DanielRuf
Copy link

Some example how GitHub does it ("by codeclimate" with the link):

Bildschirmfoto 2020-12-09 um 00 27 20

@georgestephanis
Copy link
Author

@DanielRuf As this has merged into WordPress Core, the better places to discuss this would likely be within the #core-passwords channel in Core Slack, or a Core Trac ticket on core.trac.wordpress.org.

It's also worth noting that the redirect url may not be a web-accessible domain -- it could redirect to a local application instead of a url.

@DanielRuf
Copy link

It's also worth noting that the redirect url may not be a web-accessible domain -- it could redirect to a local application instead of a url.

Sure, I am aware of this. I just wanted to point out some possible UX improvement.

Unfortunately I do not use Slack anymore and I do not know where to open the ticket and I'm unsure if a ticket about this makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants