> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.ampdb.io/api/mcp` to find what you need.

# Authentication

An Amp you run yourself in solo mode answers anyone who can reach it. A
[hosted Amp](/get-started/choose-how-to-run-amp#connect-to-a-hosted-amp) requires a token with every request: a string
that proves who you are, and that its operator uses to decide what you can do. This page shows how to give the Python
SDK your token.

The SDK sends the token with every request, in an `authorization: Bearer` header, to each service the client talks to:
the query server, the [Admin API](/managing-amp/admin-api), and the [Registry API](/sdks/python/registry).

## Prerequisites

* The Python SDK, [installed](/sdks/python#installation).
* A token from your Amp's operator.
* The Amp's query URL, and its Admin API URL if you manage datasets.

## Choose how to pass your token

The SDK takes your token from the first of these that's set:

| Source                                    | Use it when                                                          |
| ----------------------------------------- | -------------------------------------------------------------------- |
| The `auth_token` argument                 | Your code gets the token itself, for example from a secrets manager. |
| The `AMP_AUTH_TOKEN` environment variable | You have a token to use as is, like in a deployment or a CI job.     |

The SDK uses the token as is: once it expires, requests fail until you replace it.

## Use a token

Keep the token out of your code: set it in an environment variable. The SDK reads `AMP_AUTH_TOKEN` itself. It doesn't
read the URLs, so read those in your code. `AMP_ADMIN_URL` is the variable `ampctl` uses, but the query URL needs a
variable of its own, here `AMP_FLIGHT_URL`: `ampsql`'s `AMP_QUERY_URL` is an `http://` or `https://` URL, which the SDK
rejects with `ArrowKeyError: No client transport implementation for https`. The SDK needs `grpc+tls://host:port`, or
`grpc://host:port` without TLS:

```bash
export AMP_FLIGHT_URL=grpc+tls://…
export AMP_ADMIN_URL=…
export AMP_AUTH_TOKEN=…
```

```python [hosted.py]
import os

from amp import Client

client = Client(query_url=os.environ['AMP_FLIGHT_URL'], admin_url=os.environ['AMP_ADMIN_URL'])
```

To pass a token you got some other way, use `auth_token`, which takes precedence over the environment variable:

```python
client = Client(query_url=os.environ['AMP_FLIGHT_URL'], auth_token=get_token_from_vault())
```

Here `get_token_from_vault()` stands for your own code.

## Sign in

:::note
Signing in isn't available yet. To use a hosted Amp, use a token from its operator.
:::

With `auth=True`, the SDK sends the login saved on your machine, in `~/.amp/cache/amp_cli_auth`, and renews it before it
expires. `AuthService().login()` saves that login. All of this needs the sign-in service.

```python
client = Client(query_url=os.environ['AMP_FLIGHT_URL'], auth=True)
```

Setting `AMP_AUTH_TOKEN` works even if your code passes `auth=True`: the variable takes precedence. Pass either
`auth_token` or `auth=True`, not both. With both, queries use the token, but the Admin and Registry clients use your
saved login.

## Reference

The SDK's login lives in `amp.auth`. You only need it to sign in, or to work with the saved login yourself: `Client`
uses it for you when you pass `auth=True`. Signing in and refreshing need the sign-in service.

### `AuthService(config_path=None)`

Reads, refreshes, and saves a login.

* **`config_path`** (`pathlib.Path`, default `~/.amp/cache/amp_cli_auth`): the file the login is saved in. `Client`
  always uses the default.

| Method                                        | Returns                 | Does                                                                                                    |
| --------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------- |
| `login(verbose=True, auto_open_browser=True)` | `None`                  | Signs you in, and saves the login. `verbose=False` prints nothing, not even the code you need to enter. |
| `is_authenticated()`                          | `bool`                  | Whether a login is saved in the file.                                                                   |
| `get_token()`                                 | `str`                   | A valid access token, after refreshing and saving it if it expires within five minutes.                 |
| `load_auth()`                                 | `AuthStorage` or `None` | The saved login, or `None` if the file doesn't exist.                                                   |
| `save_auth(auth)`                             | `None`                  | Saves an `AuthStorage` to the file, creating its directory if needed.                                   |
| `refresh_token(auth)`                         | `AuthStorage`           | Gets a new access token for a login, and saves it.                                                      |

`get_token()` raises `FileNotFoundError` if no login is saved, and `ValueError` if the refresh fails.

### `interactive_device_login(verbose=True, auto_open_browser=True)`

Runs the sign-in that `login()` runs, and returns the login as an `AuthStorage`, without saving it. It raises
`ValueError` if the code expires before you sign in.

### `AuthStorage`

A saved login: `accessToken`, `refreshToken`, `userId`, `accounts`, and `expiry`.

## Troubleshooting

### `Not authenticated. Please run authentication first.`

You passed `auth=True`, but no login is saved in `~/.amp/cache/amp_cli_auth`. For queries, the SDK prints this error
and sends the query without a token, which a hosted Amp rejects. [Signing in](/sdks/python/authentication#sign-in) isn't available yet, so
[use a token](/sdks/python/authentication#use-a-token) instead.

### Malformed `authorization` header

The token you passed isn't a token, like a placeholder left in `AMP_AUTH_TOKEN`. Check the variable with
`echo $AMP_AUTH_TOKEN`.
