Implement Bearer Auth (#1216)

This commit is contained in:
Batuhan Taskaya 2021-12-01 20:37:57 +03:00 committed by GitHub
parent 5bf696d113
commit 00b366a81f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 51 additions and 8 deletions

View File

@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Added support for receving multiple HTTP headers with the same name, individually. ([#1207](https://github.com/httpie/httpie/issues/1207)) - Added support for receving multiple HTTP headers with the same name, individually. ([#1207](https://github.com/httpie/httpie/issues/1207))
- Added support for keeping `://` in the URL argument to allow quick conversions of pasted URLs into HTTPie calls just by adding a space after the protocol name (`$ https ://pie.dev` → `https://pie.dev`). ([#1195](https://github.com/httpie/httpie/issues/1195)) - Added support for keeping `://` in the URL argument to allow quick conversions of pasted URLs into HTTPie calls just by adding a space after the protocol name (`$ https ://pie.dev` → `https://pie.dev`). ([#1195](https://github.com/httpie/httpie/issues/1195))
- Added support for basic JSON types on `--form`/`--multipart` when using JSON only operators (`:=`/`:=@`). ([#1212](https://github.com/httpie/httpie/issues/1212)) - Added support for basic JSON types on `--form`/`--multipart` when using JSON only operators (`:=`/`:=@`). ([#1212](https://github.com/httpie/httpie/issues/1212))
- Added support for `bearer` authentication method ([#1215](https://github.com/httpie/httpie/issues/1215)).
## [2.6.0](https://github.com/httpie/httpie/compare/2.5.0...2.6.0) (2021-10-14) ## [2.6.0](https://github.com/httpie/httpie/compare/2.5.0...2.6.0) (2021-10-14)

View File

@ -1004,9 +1004,9 @@ the [sessions](#sessions) feature.
The currently supported authentication schemes are Basic and Digest (see [auth plugins](#auth-plugins) for more). There are two flags that control authentication: The currently supported authentication schemes are Basic and Digest (see [auth plugins](#auth-plugins) for more). There are two flags that control authentication:
| Flag | Arguments | | Flag | Arguments |
| ----------------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ----------------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--auth, -a` | Pass a `username:password` pair as the argument. Or, if you only specify a username (`-a username`), youll be prompted for the password before the request is sent. To send an empty password, pass `username:`. The `username:password@hostname` URL syntax is supported as well (but credentials passed via `-a` have higher priority) | | `--auth, -a` | Pass either a `username:password` pair or a `token` as the argument. If the selected authenticated method requires username/password combination and if you only specify a username (`-a username`), youll be prompted for the password before the request is sent. To send an empty password, pass `username:`. The `username:password@hostname` URL syntax is supported as well (but credentials passed via `-a` have higher priority) |
| `--auth-type, -A` | Specify the auth mechanism. Possible values are `basic`, `digest`, or the name of any [auth plugins](#auth-plugins) you have installed. The default value is `basic` so it can often be omitted | | `--auth-type, -A` | Specify the auth mechanism. Possible values are `basic`, `digest`, `bearer` or the name of any [auth plugins](#auth-plugins) you have installed. The default value is `basic` so it can often be omitted |
### Basic auth ### Basic auth
@ -1020,6 +1020,12 @@ $ http -a username:password pie.dev/basic-auth/username/password
$ http -A digest -a username:password pie.dev/digest-auth/httpie/username/password $ http -A digest -a username:password pie.dev/digest-auth/httpie/username/password
``` ```
### Bearer auth
```bash
https -A bearer -a token pie.dev/bearer
```
### Password prompt ### Password prompt
```bash ```bash

View File

@ -554,10 +554,11 @@ auth = parser.add_argument_group(title='Authentication')
auth.add_argument( auth.add_argument(
'--auth', '-a', '--auth', '-a',
default=None, default=None,
metavar='USER[:PASS]', metavar='USER[:PASS] | TOKEN',
help=''' help='''
If only the username is provided (-a username), HTTPie will prompt For username/password based authentication mechanisms (e.g
for the password. basic auth or digest auth) if only the username is provided
(-a username), HTTPie will prompt for the password.
''', ''',
) )

View File

@ -34,6 +34,16 @@ class HTTPBasicAuth(requests.auth.HTTPBasicAuth):
return f'Basic {token}' return f'Basic {token}'
class HTTPBearerAuth(requests.auth.AuthBase):
def __init__(self, token: str) -> None:
self.token = token
def __call__(self, request: requests.PreparedRequest) -> requests.PreparedRequest:
request.headers['Authorization'] = f'Bearer {self.token}'
return request
class BasicAuthPlugin(BuiltinAuthPlugin): class BasicAuthPlugin(BuiltinAuthPlugin):
name = 'Basic HTTP auth' name = 'Basic HTTP auth'
auth_type = 'basic' auth_type = 'basic'
@ -56,3 +66,14 @@ class DigestAuthPlugin(BuiltinAuthPlugin):
password: str password: str
) -> requests.auth.HTTPDigestAuth: ) -> requests.auth.HTTPDigestAuth:
return requests.auth.HTTPDigestAuth(username, password) return requests.auth.HTTPDigestAuth(username, password)
class BearerAuthPlugin(BuiltinAuthPlugin):
name = 'Bearer HTTP Auth'
auth_type = 'bearer'
netrc_parse = False
auth_parse = False
# noinspection PyMethodOverriding
def get_auth(self, **kwargs) -> requests.auth.HTTPDigestAuth:
return HTTPBearerAuth(self.raw_auth)

View File

@ -1,5 +1,5 @@
from .manager import PluginManager from .manager import PluginManager
from .builtin import BasicAuthPlugin, DigestAuthPlugin from .builtin import BasicAuthPlugin, DigestAuthPlugin, BearerAuthPlugin
from ..output.formatters.headers import HeadersFormatter from ..output.formatters.headers import HeadersFormatter
from ..output.formatters.json import JSONFormatter from ..output.formatters.json import JSONFormatter
from ..output.formatters.xml import XMLFormatter from ..output.formatters.xml import XMLFormatter
@ -13,6 +13,7 @@ plugin_manager = PluginManager()
plugin_manager.register( plugin_manager.register(
BasicAuthPlugin, BasicAuthPlugin,
DigestAuthPlugin, DigestAuthPlugin,
BearerAuthPlugin,
HeadersFormatter, HeadersFormatter,
JSONFormatter, JSONFormatter,
XMLFormatter, XMLFormatter,

View File

@ -25,6 +25,19 @@ def test_digest_auth(httpbin_both, argument_name):
assert r.json == {'authenticated': True, 'user': 'user'} assert r.json == {'authenticated': True, 'user': 'user'}
@pytest.mark.parametrize('token', [
'token_1',
'long_token' * 5,
'user:style',
])
def test_bearer_auth(httpbin_both, token):
r = http('--auth-type', 'bearer', '--auth', token,
httpbin_both + '/bearer')
assert HTTP_OK in r
assert r.json == {'authenticated': True, 'token': token}
@mock.patch('httpie.cli.argtypes.AuthCredentials._getpass', @mock.patch('httpie.cli.argtypes.AuthCredentials._getpass',
new=lambda self, prompt: 'password') new=lambda self, prompt: 'password')
def test_password_prompt(httpbin): def test_password_prompt(httpbin):