Substitute pub.dartlang.org for of pub.dev (#3358)

diff --git a/lib/src/command/lish.dart b/lib/src/command/lish.dart
index 99b5051..dc6f9f4 100644
--- a/lib/src/command/lish.dart
+++ b/lib/src/command/lish.dart
@@ -155,7 +155,8 @@
     try {
       final officialPubServers = {
         'https://pub.dartlang.org',
-        'https://pub.dev',
+        // [validateAndNormalizeHostedUrl] normalizes https://pub.dev to
+        // https://pub.dartlang.org, so we don't need to do allow that here.
 
         // Pub uses oauth2 credentials only for authenticating official pub
         // servers for security purposes (to not expose pub.dev access token to
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 7d08a55..09d9eb1 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -79,6 +79,14 @@
   if (u.path.isNotEmpty && !u.path.endsWith('/')) {
     u = u.replace(path: u.path + '/');
   }
+  // pub.dev and pub.dartlang.org are identical.
+  //
+  // We rewrite here to avoid caching both, and to avoid having different
+  // credentials for these two.
+  if (u == Uri.parse('https://pub.dev')) {
+    log.fine('Using https://pub.dartlang.org instead of https://pub.dev.');
+    u = Uri.parse('https://pub.dartlang.org');
+  }
   return u;
 }
 
diff --git a/test/token/add_token_test.dart b/test/token/add_token_test.dart
index ca68c41..65f7d56 100644
--- a/test/token/add_token_test.dart
+++ b/test/token/add_token_test.dart
@@ -150,4 +150,20 @@
       includeParentEnvironment: false,
     );
   });
+
+  test('with https://pub.dev rewrites to https://pub.dartlang.org', () async {
+    await runPub(
+      args: ['token', 'add', 'https://pub.dev'],
+      input: ['auth-token'],
+      silent: contains(
+          'Using https://pub.dartlang.org instead of https://pub.dev.'),
+    );
+
+    await d.tokensFile({
+      'version': 1,
+      'hosted': [
+        {'url': 'https://pub.dartlang.org', 'token': 'auth-token'}
+      ]
+    }).validate();
+  });
 }