# Authentication

requests supports Basic Authentication and HTTP Digest Authentication by default. There are also a number of third-party libraries for authentication with:

- OAuth
- NTLM
- Kerberos

The `requests_toolbelt.auth` provides extra authentication features in addition to those. It provides the following authentication classes:

- `requests_toolbelt.auth.guess.GuessAuth`
- `requests_toolbelt.auth.http_proxy_digest.HTTPProxyDigestAuth`
- `requests_toolbelt.auth.handler.AuthHandler`

## AuthHandler

The `AuthHandler` is a way of using a single session with multiple websites that require authentication. If you know what websites require a certain kind of authentication and what your credentials are.

Take for example a session that needs to authenticate to GitHub’s API and GitLab’s API, you would set up and use your `AuthHandler` like so:

    import requests
    from requests_toolbelt.auth.handler import AuthHandler

    def gitlab_auth(request):
        request.headers['PRIVATE-TOKEN'] = 'asecrettoken'

    handler = AuthHandler({
        'https://api.github.com': ('sigmavirus24', 'apassword'),
        'https://gitlab.com': gitlab_auth,
    })

    session = requests.Session()
    session.auth = handler
    r = session.get('https://api.github.com/user')
    # assert r.ok
    r2 = session.get('https://gitlab.com/api/v3/projects')
    # assert r2.ok

Note

You must provide both the scheme and domain for authentication. The `AuthHandler` class will check both the scheme and host to ensure your data is not accidentally exposed.

class `requests_toolbelt.auth.handler.``AuthHandler`(strategies)

  The `AuthHandler` object takes a dictionary of domains paired with authentication strategies and will use this to determine which credentials to use when making a request. For example, you could do the following:

      from requests import HTTPDigestAuth
      from requests_toolbelt.auth.handler import AuthHandler

      import requests

      auth = AuthHandler({
          'https://api.github.com': ('sigmavirus24', 'fakepassword'),
          'https://example.com': HTTPDigestAuth('username', 'password')
      })

      r = requests.get('https://api.github.com/user', auth=auth)
      # => <Response [200]>
      r = requests.get('https://example.com/some/path', auth=auth)
      # => <Response [200]>

      s = requests.Session()
      s.auth = auth
      r = s.get('https://api.github.com/user')
      # => <Response [200]>

  Warning

  `requests.auth.HTTPDigestAuth` is not yet thread-safe. If you use `AuthHandler` across multiple threads you should instantiate a new AuthHandler for each thread with a new HTTPDigestAuth instance for each thread.

  `add_strategy`(domain, strategy)

    Add a new domain and authentication strategy.

    Parameters:

    - domain (str) – The domain you wish to match against. For example: `'https://api.github.com'`
    - strategy (str) – The authentication strategy you wish to use for that domain. For example: `('username', 'password')` or `requests.HTTPDigestAuth('username', 'password')`

        a = AuthHandler({})
        a.add_strategy('https://api.github.com', ('username', 'password'))

  `get_strategy_for`(url)

    Retrieve the authentication strategy for a specified URL.

    Parameters: | url (str) – The full URL you will be making a request against. For example, `'https://api.github.com/user'`
    Returns: | Callable that adds authentication to a request.

        import requests
        a = AuthHandler({'example.com', ('foo', 'bar')})
        strategy = a.get_strategy_for('http://example.com/example')
        assert isinstance(strategy, requests.auth.HTTPBasicAuth)

  `remove_strategy`(domain)

    Remove the domain and strategy from the collection of strategies.

    Parameters: | domain (str) – The domain you wish remove. For example, `'https://api.github.com'`.

        a = AuthHandler({'example.com', ('foo', 'bar')})
        a.remove_strategy('example.com')
        assert a.strategies == {}

## GuessAuth

The `GuessAuth` authentication class automatically detects whether to use basic auth or digest auth:

    import requests
    from requests_toolbelt.auth import GuessAuth

    requests.get('http://httpbin.org/basic-auth/user/passwd',
                 auth=GuessAuth('user', 'passwd'))
    requests.get('http://httpbin.org/digest-auth/auth/user/passwd',
                 auth=GuessAuth('user', 'passwd'))

Detection of the auth type is done via the `WWW-Authenticate` header sent by the server. This requires an additional request in case of basic auth, as usually basic auth is sent preemptively. If the server didn’t explicitly require authentication, no credentials are sent.

class `requests_toolbelt.auth.guess.``GuessAuth`(username, password)

  Guesses the auth type by the WWW-Authentication header.

## GuessProxyAuth

The `GuessProxyAuth` handler will automatically detect whether to use basic authentication or digest authentication when authenticating to the provided proxy.

    import requests
    from requests_toolbelt.auth.guess import GuessProxyAuth

    proxies = {
        "http": "http://PROXYSERVER:PROXYPORT",
        "https": "http://PROXYSERVER:PROXYPORT",
    }
    requests.get('http://httpbin.org/basic-auth/user/passwd',
                 auth=GuessProxyAuth('user', 'passwd', 'proxyusr', 'proxypass'),
                 proxies=proxies)
    requests.get('http://httpbin.org/digest-auth/auth/user/passwd',
                 auth=GuessProxyAuth('user', 'passwd', 'proxyusr', 'proxypass'),
                 proxies=proxies)

Detection of the auth type is done via the `Proxy-Authenticate` header sent by the server. This requires an additional request in case of basic auth, as usually basic auth is sent preemptively. If the server didn’t explicitly require authentication, no credentials are sent.

class `requests_toolbelt.auth.guess.``GuessProxyAuth`(username=None, password=None, proxy_username=None, proxy_password=None)

  Guesses the auth type by WWW-Authentication and Proxy-Authentication headers

## HTTPProxyDigestAuth

The `HTTPProxyDigestAuth` use digest authentication between the client and the proxy.

    import requests
    from requests_toolbelt.auth.http_proxy_digest import HTTPProxyDigestAuth

    proxies = {
        "http": "http://PROXYSERVER:PROXYPORT",
        "https": "https://PROXYSERVER:PROXYPORT",
    }
    url = "https://toolbelt.readthedocs.org/"
    auth = HTTPProxyDigestAuth("USERNAME", "PASSWORD")
    requests.get(url, proxies=proxies, auth=auth)

Program would raise error if the username or password is rejected by the proxy.

class `requests_toolbelt.auth.http_proxy_digest.``HTTPProxyDigestAuth`(*args, **kwargs)

  HTTP digest authentication between proxy

  Parameters: | stale_rejects (int) – The number of rejects indicate that: the client may wish to simply retry the request with a new encrypted response, without reprompting the user for a new username and password. i.e., retry build_digest_header