# Create and Use API Keys This guide applies to **multi-user** Tiled deployments, i.e. deployments configured with an authentication provider. ```{note} **Single-user** deployments run with a single API key. By default, it is randomly generated and printed to the console at server startup, like so: $ tiled serve pyobject tiled.examples.generated:tree Generating large example data... Done generating example data. Use the following URL to connect to Tiled: "http://127.0.0.1:8000?api_key=8df0146c93e9add287d0e7f84a165ba4bd3517bbb3c7c6b4d963c3e1549d0311" This guide does not apply to single-user deployments like this. ``` ## Why use API keys? Users can log in to Tiled with a simple username/password or through a third party like ORICD or Google, as demonstrated in the tutorial {doc}`../tutorials/login`. For interactive workflows in Python, this the most convenient way to authenticate. But in other situations, it can more convenient to generate and use an API key. An API key uses a comparatively simpler interaction, without an interactive prompt or the need to periodically "refresh" a session to keep it active. This is useful when: * The code using tiled is running in an unsupervised, automated fashion or scaled across many workers, such as in an HPC job, where is it not possible to provide credentials interactively. * You are connecting from a generic web client like a web browser or `curl`, which has no built-in integration with Tiled or with OpenAPI+OAuth2. ## Create an API Key To follow along, you may start a Tiled server with a simple authentication provider, as shown. Alternatively, you may use an existing authenticated Tiled server, such as `https://tiled-demo.blueskyproject.io`; if you do, replace `http://localhost:8000` in the example below with that address. ``` # You can find example_configs/ in the root of the tiled source code repository. ALICE_PASSWORD=secret1 tiled serve config example_configs/toy_authentication.yml ``` Using the Tiled commandline interface, log in as `alice` using the password `secret1`. ``` $ tiled profile create http://localhost:8000 $ tiled login Username: alice Password: ``` Create a new API key. ``` $ tiled api_key create 48e8f8598940fa0f3e80b406def606e17e815a2c76fe21350a99d6d9935371d11533b318 ``` This text is the API key. **It should be handled as a secret.** ## Use the API Key in Python We can use it in the Python client: ```py >>> from tiled.client import from_url >>> API_KEY = "YOUR_KEY_HERE" >>> c = from_uri("http://localhost:8000", api_key=API_KEY) ``` API keys should never be placed directly in scripts or notebooks. Instead, set the environment variable `TILED_API_KEY`. ``` export TILED_API_KEY=YOUR_KEY_HERE ``` and then start Python (or IPython, or Jupyter, or...). The Python client will use that, unless it is explicitly passed different credentials. ```py >>> from tiled.client import from_url >>> c = from_uri("http://localhost:8000") # uses TILED_API_KEY, if set ``` ## Use the API Key in other web clients We can use in other web clients as well. For example, using [HTTPie](https://httpie.io/) we can see that unauthenticated requests are refused ``` $ http http://localhost:8000/api/v1/metadata/ HTTP/1.1 401 Unauthorized content-length: 30 content-type: application/json date: Mon, 31 Jan 2022 17:30:06 GMT server: uvicorn server-timing: app;dur=2.6 set-cookie: tiled_csrf=bZLhKsXVE2VirgXQncHsHn4Y0Wwwr66U0T0hqarJyfw; HttpOnly; Path=/; SameSite=lax x-tiled-root: http://localhost:8000/api/v1 { "detail": "Not authenticated" } ``` but passing the API key in the `Authorization` header as `Apikey YOUR_KEY_HERE` is accepted. (Note the use of `'` quotes.) ``` $ http http://localhost:8000/api/v1/metadata/ 'Authorization:Apikey 48e8f8598940fa0f3e80b406def606e17e815a2c76fe21350a99d6d9935371d11533b318' HTTP/1.1 200 OK content-length: 320 content-type: application/json date: Mon, 31 Jan 2022 17:34:48 GMT etag: c7d94c99b0a3cd6e102a78520db84bef server: uvicorn server-timing: tok;dur=0.0, pack;dur=0.0, app;dur=15.2 set-cookie: tiled_csrf=InE4mplUO0goPxf4V07tVuLSLUvDqhgtALTHYoC3T3s; HttpOnly; Path=/; SameSite=lax ``` The API key can also be passed in the URL like `http://localhost:8000/api/v1/metadata/?api_key=YOUR_KEY_HERE`. Using the `Authorization` header is preferred (more secure) but in some situations, as in pasting a link into a web browser, the URL is the only option. ## Manage API Keys We can use the tiled commandline interface to examine and revoke API keys as well. ``` $ tiled api_key Usage: tiled api_key [OPTIONS] COMMAND [ARGS]... Create, list, and revoke API keys. Options: --help Show this message and exit. Commands: create list revoke ``` We can see the key that we made above in the list. ``` $ tiled api_key list First 8 Expires at (UTC) Latest activity Note Scopes 48e8f859 - 2022-01-31T18:32:33 inherit ``` By default, an API key inherits all the same access as the user who is for. If an API key will be used for a specific task, it is good security hygiene to give it only the privileges it needs for that task. It is also recommended to set a limited lifetimes so that if the key is unknowingly leaked it will not continue to work forever. For example, this command creates an API key that will expire in 10 minutes (600 seconds) and can search/list metadata but cannot download array data. ``` $ tiled api_key create --expires-in 600 --scopes read:metadata ba9af604023a829ab22edb786168d6e1b97cef68c54c6d95d7fad5e3e6347fa131263581 ``` See {doc}`../reference/scopes` for the full list of scopes and their capabilities. ``` $ tiled api_key list First 8 Expires at (UTC) Latest activity Note Scopes 48e8f859 - 2022-01-31T18:32:33 inherit ba9af604 2022-01-31T23:03:57 - read:metadata ``` Finally, the `--note` option can be used to label an API key as a reminder of where or how it is being used. ``` $ tiled api_key create --note="Data validation pipeline" --scopes read:metadata read:data 573928c62e53096321fb874847bcc6a90ea636eebd8acbd7c5e9d18d2859847b3bfb4f19 $ tiled api_key list First 8 Expires at (UTC) Latest activity Note Scopes 48e8f859 - 2022-01-31T18:32:33 inherit ba9af604 2022-01-31T23:03:57 - read:metadata 573928c6 - - Data validation pipeline read:metadata read:data ``` If an API key is no longer need or accidentally leaked, it should be revoked. It can be identified by its first eight characters, as shown in the the output of `tiled api_key list`. ``` $ tiled api_key revoke 573928c6 $ tiled api_key list First 8 Expires at (UTC) Latest activity Note Scopes 48e8f859 - 2022-01-31T18:32:33 inherit ba9af604 2022-01-31T23:03:57 - read:metadata ``` Passing the full key also works, if you have it handy. There is no need to trim just the first eight.