We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Auth fails with long passwords
See https://github.com/docker/docker/issues/16840

docker-py is encoding `X-Registry-Auth` with regular base64 and not the url safe version of base64 that jwt tokens use.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `docker/auth/auth.py`
Content:
```
1 # Copyright 2013 dotCloud inc.
2 
3 #    Licensed under the Apache License, Version 2.0 (the "License");
4 #    you may not use this file except in compliance with the License.
5 #    You may obtain a copy of the License at
6 
7 #        http://www.apache.org/licenses/LICENSE-2.0
8 
9 #    Unless required by applicable law or agreed to in writing, software
10 #    distributed under the License is distributed on an "AS IS" BASIS,
11 #    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 #    See the License for the specific language governing permissions and
13 #    limitations under the License.
14 
15 import base64
16 import fileinput
17 import json
18 import logging
19 import os
20 import warnings
21 
22 import six
23 
24 from .. import constants
25 from .. import errors
26 
27 INDEX_NAME = 'index.docker.io'
28 INDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME)
29 DOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json')
30 LEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg'
31 
32 log = logging.getLogger(__name__)
33 
34 
35 def resolve_repository_name(repo_name, insecure=False):
36     if insecure:
37         warnings.warn(
38             constants.INSECURE_REGISTRY_DEPRECATION_WARNING.format(
39                 'resolve_repository_name()'
40             ), DeprecationWarning
41         )
42 
43     if '://' in repo_name:
44         raise errors.InvalidRepository(
45             'Repository name cannot contain a scheme ({0})'.format(repo_name))
46     parts = repo_name.split('/', 1)
47     if '.' not in parts[0] and ':' not in parts[0] and parts[0] != 'localhost':
48         # This is a docker index repo (ex: foo/bar or ubuntu)
49         return INDEX_NAME, repo_name
50     if len(parts) < 2:
51         raise errors.InvalidRepository(
52             'Invalid repository name ({0})'.format(repo_name))
53 
54     if 'index.docker.io' in parts[0]:
55         raise errors.InvalidRepository(
56             'Invalid repository name, try "{0}" instead'.format(parts[1])
57         )
58 
59     return parts[0], parts[1]
60 
61 
62 def resolve_authconfig(authconfig, registry=None):
63     """
64     Returns the authentication data from the given auth configuration for a
65     specific registry. As with the Docker client, legacy entries in the config
66     with full URLs are stripped down to hostnames before checking for a match.
67     Returns None if no match was found.
68     """
69     # Default to the public index server
70     registry = convert_to_hostname(registry) if registry else INDEX_NAME
71     log.debug("Looking for auth entry for {0}".format(repr(registry)))
72 
73     if registry in authconfig:
74         log.debug("Found {0}".format(repr(registry)))
75         return authconfig[registry]
76 
77     for key, config in six.iteritems(authconfig):
78         if convert_to_hostname(key) == registry:
79             log.debug("Found {0}".format(repr(key)))
80             return config
81 
82     log.debug("No entry found")
83     return None
84 
85 
86 def convert_to_hostname(url):
87     return url.replace('http://', '').replace('https://', '').split('/', 1)[0]
88 
89 
90 def encode_auth(auth_info):
91     return base64.b64encode(auth_info.get('username', '') + b':' +
92                             auth_info.get('password', ''))
93 
94 
95 def decode_auth(auth):
96     if isinstance(auth, six.string_types):
97         auth = auth.encode('ascii')
98     s = base64.b64decode(auth)
99     login, pwd = s.split(b':', 1)
100     return login.decode('ascii'), pwd.decode('ascii')
101 
102 
103 def encode_header(auth):
104     auth_json = json.dumps(auth).encode('ascii')
105     return base64.b64encode(auth_json)
106 
107 
108 def parse_auth(entries):
109     """
110     Parses authentication entries
111 
112     Args:
113       entries: Dict of authentication entries.
114 
115     Returns:
116       Authentication registry.
117     """
118 
119     conf = {}
120     for registry, entry in six.iteritems(entries):
121         username, password = decode_auth(entry['auth'])
122         log.debug(
123             'Found entry (registry={0}, username={1})'
124             .format(repr(registry), repr(username))
125         )
126         conf[registry] = {
127             'username': username,
128             'password': password,
129             'email': entry['email'],
130             'serveraddress': registry,
131         }
132     return conf
133 
134 
135 def load_config(config_path=None):
136     """
137     Loads authentication data from a Docker configuration file in the given
138     root directory or if config_path is passed use given path.
139     """
140     conf = {}
141     data = None
142 
143     # Prefer ~/.docker/config.json.
144     config_file = config_path or os.path.join(os.path.expanduser('~'),
145                                               DOCKER_CONFIG_FILENAME)
146 
147     log.debug("Trying {0}".format(config_file))
148 
149     if os.path.exists(config_file):
150         try:
151             with open(config_file) as f:
152                 for section, data in six.iteritems(json.load(f)):
153                     if section != 'auths':
154                         continue
155                     log.debug("Found 'auths' section")
156                     return parse_auth(data)
157             log.debug("Couldn't find 'auths' section")
158         except (IOError, KeyError, ValueError) as e:
159             # Likely missing new Docker config file or it's in an
160             # unknown format, continue to attempt to read old location
161             # and format.
162             log.debug(e)
163             pass
164     else:
165         log.debug("File doesn't exist")
166 
167     config_file = config_path or os.path.join(os.path.expanduser('~'),
168                                               LEGACY_DOCKER_CONFIG_FILENAME)
169 
170     log.debug("Trying {0}".format(config_file))
171 
172     if not os.path.exists(config_file):
173         log.debug("File doesn't exist - returning empty config")
174         return {}
175 
176     log.debug("Attempting to parse as JSON")
177     try:
178         with open(config_file) as f:
179             return parse_auth(json.load(f))
180     except Exception as e:
181         log.debug(e)
182         pass
183 
184     # If that fails, we assume the configuration file contains a single
185     # authentication token for the public registry in the following format:
186     #
187     # auth = AUTH_TOKEN
188     # email = email@domain.com
189     log.debug("Attempting to parse legacy auth file format")
190     try:
191         data = []
192         for line in fileinput.input(config_file):
193             data.append(line.strip().split(' = ')[1])
194         if len(data) < 2:
195             # Not enough data
196             raise errors.InvalidConfigFile(
197                 'Invalid or empty configuration file!')
198 
199         username, password = decode_auth(data[0])
200         conf[INDEX_NAME] = {
201             'username': username,
202             'password': password,
203             'email': data[1],
204             'serveraddress': INDEX_URL,
205         }
206         return conf
207     except Exception as e:
208         log.debug(e)
209         pass
210 
211     log.debug("All parsing attempts failed - returning empty config")
212     return {}
213
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/docker/auth/auth.py b/docker/auth/auth.py
--- a/docker/auth/auth.py
+++ b/docker/auth/auth.py
@@ -102,7 +102,7 @@
 
 def encode_header(auth):
     auth_json = json.dumps(auth).encode('ascii')
-    return base64.b64encode(auth_json)
+    return base64.urlsafe_b64encode(auth_json)
 
 
 def parse_auth(entries):

{"golden_diff": "diff --git a/docker/auth/auth.py b/docker/auth/auth.py\n--- a/docker/auth/auth.py\n+++ b/docker/auth/auth.py\n@@ -102,7 +102,7 @@\n \n def encode_header(auth):\n     auth_json = json.dumps(auth).encode('ascii')\n-    return base64.b64encode(auth_json)\n+    return base64.urlsafe_b64encode(auth_json)\n \n \n def parse_auth(entries):\n", "issue": "Auth fails with long passwords\nSee https://github.com/docker/docker/issues/16840\n\ndocker-py is encoding `X-Registry-Auth` with regular base64 and not the url safe version of base64 that jwt tokens use.\n\n", "before_files": [{"content": "# Copyright 2013 dotCloud inc.\n\n#    Licensed under the Apache License, Version 2.0 (the \"License\");\n#    you may not use this file except in compliance with the License.\n#    You may obtain a copy of the License at\n\n#        http://www.apache.org/licenses/LICENSE-2.0\n\n#    Unless required by applicable law or agreed to in writing, software\n#    distributed under the License is distributed on an \"AS IS\" BASIS,\n#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#    See the License for the specific language governing permissions and\n#    limitations under the License.\n\nimport base64\nimport fileinput\nimport json\nimport logging\nimport os\nimport warnings\n\nimport six\n\nfrom .. import constants\nfrom .. import errors\n\nINDEX_NAME = 'index.docker.io'\nINDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME)\nDOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json')\nLEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg'\n\nlog = logging.getLogger(__name__)\n\n\ndef resolve_repository_name(repo_name, insecure=False):\n    if insecure:\n        warnings.warn(\n            constants.INSECURE_REGISTRY_DEPRECATION_WARNING.format(\n                'resolve_repository_name()'\n            ), DeprecationWarning\n        )\n\n    if '://' in repo_name:\n        raise errors.InvalidRepository(\n            'Repository name cannot contain a scheme ({0})'.format(repo_name))\n    parts = repo_name.split('/', 1)\n    if '.' not in parts[0] and ':' not in parts[0] and parts[0] != 'localhost':\n        # This is a docker index repo (ex: foo/bar or ubuntu)\n        return INDEX_NAME, repo_name\n    if len(parts) < 2:\n        raise errors.InvalidRepository(\n            'Invalid repository name ({0})'.format(repo_name))\n\n    if 'index.docker.io' in parts[0]:\n        raise errors.InvalidRepository(\n            'Invalid repository name, try \"{0}\" instead'.format(parts[1])\n        )\n\n    return parts[0], parts[1]\n\n\ndef resolve_authconfig(authconfig, registry=None):\n    \"\"\"\n    Returns the authentication data from the given auth configuration for a\n    specific registry. As with the Docker client, legacy entries in the config\n    with full URLs are stripped down to hostnames before checking for a match.\n    Returns None if no match was found.\n    \"\"\"\n    # Default to the public index server\n    registry = convert_to_hostname(registry) if registry else INDEX_NAME\n    log.debug(\"Looking for auth entry for {0}\".format(repr(registry)))\n\n    if registry in authconfig:\n        log.debug(\"Found {0}\".format(repr(registry)))\n        return authconfig[registry]\n\n    for key, config in six.iteritems(authconfig):\n        if convert_to_hostname(key) == registry:\n            log.debug(\"Found {0}\".format(repr(key)))\n            return config\n\n    log.debug(\"No entry found\")\n    return None\n\n\ndef convert_to_hostname(url):\n    return url.replace('http://', '').replace('https://', '').split('/', 1)[0]\n\n\ndef encode_auth(auth_info):\n    return base64.b64encode(auth_info.get('username', '') + b':' +\n                            auth_info.get('password', ''))\n\n\ndef decode_auth(auth):\n    if isinstance(auth, six.string_types):\n        auth = auth.encode('ascii')\n    s = base64.b64decode(auth)\n    login, pwd = s.split(b':', 1)\n    return login.decode('ascii'), pwd.decode('ascii')\n\n\ndef encode_header(auth):\n    auth_json = json.dumps(auth).encode('ascii')\n    return base64.b64encode(auth_json)\n\n\ndef parse_auth(entries):\n    \"\"\"\n    Parses authentication entries\n\n    Args:\n      entries: Dict of authentication entries.\n\n    Returns:\n      Authentication registry.\n    \"\"\"\n\n    conf = {}\n    for registry, entry in six.iteritems(entries):\n        username, password = decode_auth(entry['auth'])\n        log.debug(\n            'Found entry (registry={0}, username={1})'\n            .format(repr(registry), repr(username))\n        )\n        conf[registry] = {\n            'username': username,\n            'password': password,\n            'email': entry['email'],\n            'serveraddress': registry,\n        }\n    return conf\n\n\ndef load_config(config_path=None):\n    \"\"\"\n    Loads authentication data from a Docker configuration file in the given\n    root directory or if config_path is passed use given path.\n    \"\"\"\n    conf = {}\n    data = None\n\n    # Prefer ~/.docker/config.json.\n    config_file = config_path or os.path.join(os.path.expanduser('~'),\n                                              DOCKER_CONFIG_FILENAME)\n\n    log.debug(\"Trying {0}\".format(config_file))\n\n    if os.path.exists(config_file):\n        try:\n            with open(config_file) as f:\n                for section, data in six.iteritems(json.load(f)):\n                    if section != 'auths':\n                        continue\n                    log.debug(\"Found 'auths' section\")\n                    return parse_auth(data)\n            log.debug(\"Couldn't find 'auths' section\")\n        except (IOError, KeyError, ValueError) as e:\n            # Likely missing new Docker config file or it's in an\n            # unknown format, continue to attempt to read old location\n            # and format.\n            log.debug(e)\n            pass\n    else:\n        log.debug(\"File doesn't exist\")\n\n    config_file = config_path or os.path.join(os.path.expanduser('~'),\n                                              LEGACY_DOCKER_CONFIG_FILENAME)\n\n    log.debug(\"Trying {0}\".format(config_file))\n\n    if not os.path.exists(config_file):\n        log.debug(\"File doesn't exist - returning empty config\")\n        return {}\n\n    log.debug(\"Attempting to parse as JSON\")\n    try:\n        with open(config_file) as f:\n            return parse_auth(json.load(f))\n    except Exception as e:\n        log.debug(e)\n        pass\n\n    # If that fails, we assume the configuration file contains a single\n    # authentication token for the public registry in the following format:\n    #\n    # auth = AUTH_TOKEN\n    # email = email@domain.com\n    log.debug(\"Attempting to parse legacy auth file format\")\n    try:\n        data = []\n        for line in fileinput.input(config_file):\n            data.append(line.strip().split(' = ')[1])\n        if len(data) < 2:\n            # Not enough data\n            raise errors.InvalidConfigFile(\n                'Invalid or empty configuration file!')\n\n        username, password = decode_auth(data[0])\n        conf[INDEX_NAME] = {\n            'username': username,\n            'password': password,\n            'email': data[1],\n            'serveraddress': INDEX_URL,\n        }\n        return conf\n    except Exception as e:\n        log.debug(e)\n        pass\n\n    log.debug(\"All parsing attempts failed - returning empty config\")\n    return {}\n", "path": "docker/auth/auth.py"}], "after_files": [{"content": "# Copyright 2013 dotCloud inc.\n\n#    Licensed under the Apache License, Version 2.0 (the \"License\");\n#    you may not use this file except in compliance with the License.\n#    You may obtain a copy of the License at\n\n#        http://www.apache.org/licenses/LICENSE-2.0\n\n#    Unless required by applicable law or agreed to in writing, software\n#    distributed under the License is distributed on an \"AS IS\" BASIS,\n#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#    See the License for the specific language governing permissions and\n#    limitations under the License.\n\nimport base64\nimport fileinput\nimport json\nimport logging\nimport os\nimport warnings\n\nimport six\n\nfrom .. import constants\nfrom .. import errors\n\nINDEX_NAME = 'index.docker.io'\nINDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME)\nDOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json')\nLEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg'\n\nlog = logging.getLogger(__name__)\n\n\ndef resolve_repository_name(repo_name, insecure=False):\n    if insecure:\n        warnings.warn(\n            constants.INSECURE_REGISTRY_DEPRECATION_WARNING.format(\n                'resolve_repository_name()'\n            ), DeprecationWarning\n        )\n\n    if '://' in repo_name:\n        raise errors.InvalidRepository(\n            'Repository name cannot contain a scheme ({0})'.format(repo_name))\n    parts = repo_name.split('/', 1)\n    if '.' not in parts[0] and ':' not in parts[0] and parts[0] != 'localhost':\n        # This is a docker index repo (ex: foo/bar or ubuntu)\n        return INDEX_NAME, repo_name\n    if len(parts) < 2:\n        raise errors.InvalidRepository(\n            'Invalid repository name ({0})'.format(repo_name))\n\n    if 'index.docker.io' in parts[0]:\n        raise errors.InvalidRepository(\n            'Invalid repository name, try \"{0}\" instead'.format(parts[1])\n        )\n\n    return parts[0], parts[1]\n\n\ndef resolve_authconfig(authconfig, registry=None):\n    \"\"\"\n    Returns the authentication data from the given auth configuration for a\n    specific registry. As with the Docker client, legacy entries in the config\n    with full URLs are stripped down to hostnames before checking for a match.\n    Returns None if no match was found.\n    \"\"\"\n    # Default to the public index server\n    registry = convert_to_hostname(registry) if registry else INDEX_NAME\n    log.debug(\"Looking for auth entry for {0}\".format(repr(registry)))\n\n    if registry in authconfig:\n        log.debug(\"Found {0}\".format(repr(registry)))\n        return authconfig[registry]\n\n    for key, config in six.iteritems(authconfig):\n        if convert_to_hostname(key) == registry:\n            log.debug(\"Found {0}\".format(repr(key)))\n            return config\n\n    log.debug(\"No entry found\")\n    return None\n\n\ndef convert_to_hostname(url):\n    return url.replace('http://', '').replace('https://', '').split('/', 1)[0]\n\n\ndef encode_auth(auth_info):\n    return base64.b64encode(auth_info.get('username', '') + b':' +\n                            auth_info.get('password', ''))\n\n\ndef decode_auth(auth):\n    if isinstance(auth, six.string_types):\n        auth = auth.encode('ascii')\n    s = base64.b64decode(auth)\n    login, pwd = s.split(b':', 1)\n    return login.decode('ascii'), pwd.decode('ascii')\n\n\ndef encode_header(auth):\n    auth_json = json.dumps(auth).encode('ascii')\n    return base64.urlsafe_b64encode(auth_json)\n\n\ndef parse_auth(entries):\n    \"\"\"\n    Parses authentication entries\n\n    Args:\n      entries: Dict of authentication entries.\n\n    Returns:\n      Authentication registry.\n    \"\"\"\n\n    conf = {}\n    for registry, entry in six.iteritems(entries):\n        username, password = decode_auth(entry['auth'])\n        log.debug(\n            'Found entry (registry={0}, username={1})'\n            .format(repr(registry), repr(username))\n        )\n        conf[registry] = {\n            'username': username,\n            'password': password,\n            'email': entry['email'],\n            'serveraddress': registry,\n        }\n    return conf\n\n\ndef load_config(config_path=None):\n    \"\"\"\n    Loads authentication data from a Docker configuration file in the given\n    root directory or if config_path is passed use given path.\n    \"\"\"\n    conf = {}\n    data = None\n\n    # Prefer ~/.docker/config.json.\n    config_file = config_path or os.path.join(os.path.expanduser('~'),\n                                              DOCKER_CONFIG_FILENAME)\n\n    log.debug(\"Trying {0}\".format(config_file))\n\n    if os.path.exists(config_file):\n        try:\n            with open(config_file) as f:\n                for section, data in six.iteritems(json.load(f)):\n                    if section != 'auths':\n                        continue\n                    log.debug(\"Found 'auths' section\")\n                    return parse_auth(data)\n            log.debug(\"Couldn't find 'auths' section\")\n        except (IOError, KeyError, ValueError) as e:\n            # Likely missing new Docker config file or it's in an\n            # unknown format, continue to attempt to read old location\n            # and format.\n            log.debug(e)\n            pass\n    else:\n        log.debug(\"File doesn't exist\")\n\n    config_file = config_path or os.path.join(os.path.expanduser('~'),\n                                              LEGACY_DOCKER_CONFIG_FILENAME)\n\n    log.debug(\"Trying {0}\".format(config_file))\n\n    if not os.path.exists(config_file):\n        log.debug(\"File doesn't exist - returning empty config\")\n        return {}\n\n    log.debug(\"Attempting to parse as JSON\")\n    try:\n        with open(config_file) as f:\n            return parse_auth(json.load(f))\n    except Exception as e:\n        log.debug(e)\n        pass\n\n    # If that fails, we assume the configuration file contains a single\n    # authentication token for the public registry in the following format:\n    #\n    # auth = AUTH_TOKEN\n    # email = email@domain.com\n    log.debug(\"Attempting to parse legacy auth file format\")\n    try:\n        data = []\n        for line in fileinput.input(config_file):\n            data.append(line.strip().split(' = ')[1])\n        if len(data) < 2:\n            # Not enough data\n            raise errors.InvalidConfigFile(\n                'Invalid or empty configuration file!')\n\n        username, password = decode_auth(data[0])\n        conf[INDEX_NAME] = {\n            'username': username,\n            'password': password,\n            'email': data[1],\n            'serveraddress': INDEX_URL,\n        }\n        return conf\n    except Exception as e:\n        log.debug(e)\n        pass\n\n    log.debug(\"All parsing attempts failed - returning empty config\")\n    return {}\n", "path": "docker/auth/auth.py"}]}