<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[59084] trunk: App Passwords: Don't prevent non-unique App Password names.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/59084">59084</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/59084","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>TimothyBlynJacobs</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2024-09-24 16:38:36 +0000 (Tue, 24 Sep 2024)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>App Passwords: Don't prevent non-unique App Password names.

In <a href="https://core.trac.wordpress.org/changeset/50030">[50030]</a> we enforced that Application Passwords have unique names. This was done with the assumption that applications would not connect to a user multiple times. However, in practice we've seen applications run into issues with the unique name constraint. Depending on the app, they may not know if they've been authorized before, or they may intentionally allow connecting multiple times. To prevent friction, App developers need to make their App Name unique, and in doing so often include things like the current date & time, which is already included in the App Passwords list table.

This commit removes this requirement to simplify usage of the Authorize Application flow.

Props mark-k, Boniu91, timothyblynjacobs, peterwilsoncc.
Fixes <a href="https://core.trac.wordpress.org/ticket/54213">#54213</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesclasswpapplicationpasswordsphp">trunk/src/wp-includes/class-wp-application-passwords.php</a></li>
<li><a href="#trunktestse2especsprofileapplicationspasswordstestjs">trunk/tests/e2e/specs/profile/applications-passwords.test.js</a></li>
<li><a href="#trunktestsphpunittestsrestapiapplicationpasswordsphp">trunk/tests/phpunit/tests/rest-api/application-passwords.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesclasswpapplicationpasswordsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-application-passwords.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-application-passwords.php  2024-09-24 07:33:55 UTC (rev 59083)
+++ trunk/src/wp-includes/class-wp-application-passwords.php    2024-09-24 16:38:36 UTC (rev 59084)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -94,10 +94,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ), array( 'status' => 400 ) );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( self::application_name_exists_for_user( $user_id, $args['name'] ) ) {
-                       return new WP_Error( 'application_password_duplicate_name', __( 'Each application name should be unique.' ), array( 'status' => 409 ) );
-               }
-
</del><span class="cx" style="display: block; padding: 0 10px">                 $new_password    = wp_generate_password( static::PW_LENGTH, false );
</span><span class="cx" style="display: block; padding: 0 10px">                $hashed_password = wp_hash_password( $new_password );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunktestse2especsprofileapplicationspasswordstestjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/e2e/specs/profile/applications-passwords.test.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/specs/profile/applications-passwords.test.js      2024-09-24 07:33:55 UTC (rev 59083)
+++ trunk/tests/e2e/specs/profile/applications-passwords.test.js        2024-09-24 16:38:36 UTC (rev 59084)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -40,23 +40,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px">        } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        test('should not allow to create two applications passwords with the same name', async ( {
-               page,
-               applicationPasswords
-       } ) => {
-               await applicationPasswords.create();
-               await applicationPasswords.create();
-
-               const errorMessage = page.getByRole( 'alert' );
-
-               await expect( errorMessage ).toHaveClass( /notice-error/ );
-               await expect(
-                       errorMessage
-               ).toContainText(
-                       'Each application name should be unique.'
-               );
-       });
-
</del><span class="cx" style="display: block; padding: 0 10px">         test( 'should correctly revoke a single application password', async ( {
</span><span class="cx" style="display: block; padding: 0 10px">                page,
</span><span class="cx" style="display: block; padding: 0 10px">                applicationPasswords
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiapplicationpasswordsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/application-passwords.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/application-passwords.php      2024-09-24 07:33:55 UTC (rev 59083)
+++ trunk/tests/phpunit/tests/rest-api/application-passwords.php        2024-09-24 16:38:36 UTC (rev 59084)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -77,14 +77,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                ),
</span><span class="cx" style="display: block; padding: 0 10px">                                'args'     => array( 'name' => '<script>console.log("Hello")</script>' ),
</span><span class="cx" style="display: block; padding: 0 10px">                        ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'application_password_duplicate_name when name exists' => array(
-                               'expected' => array(
-                                       'error_code'    => 'application_password_duplicate_name',
-                                       'error_message' => 'Each application name should be unique.',
-                               ),
-                               'args'     => array( 'name' => 'test2' ),
-                               'names'    => array( 'test1', 'test2' ),
-                       ),
</del><span class="cx" style="display: block; padding: 0 10px">                 );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -196,4 +188,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @ticket 51941
+        */
+       public function test_can_create_duplicate_app_password_names() {
+               $created = WP_Application_Passwords::create_new_application_password( self::$user_id, array( 'name' => 'My App' ) );
+               $this->assertNotWPError( $created, 'First attempt to create an application password should not return an error' );
+               $created = WP_Application_Passwords::create_new_application_password( self::$user_id, array( 'name' => 'My App' ) );
+               $this->assertNotWPError( $created, 'Second attempt to create an application password should not return an error' );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>

</body>
</html>