# Create temporary credentials

> Create an access key, secret and session token that stop working on their own, limited to a bucket, a key prefix and read-only or read-write.

Source: https://www.coritan.com/docs/object-storage/temporary-credentials/

In the dashboard:

- /dashboard/storage/…/keys: https://www.coritan.com/dashboard/storage

*Temporary credentials* are an access key ID, a secret access key and a *session token* that stop working on their own, from 15 minutes to 12 hours after you create them. Use them to give an app, a build job or a person access to one bucket, or to one folder in it, for as long as the work takes, without handing out a long-lived access key.

You create them on the service's **Access keys** tab or through the API. They work with any S3 client that can send a session token, such as the AWS CLI and the AWS SDKs.

## Before you begin

- Sign in to the [dashboard](https://www.coritan.com/dashboard/storage) and open the service.
- The service must be `active`.
- To limit the credentials to one bucket, create the bucket first ([Create a bucket](/docs/object-storage/buckets/#create-a-bucket)).
- Check that the **Temporary credentials…** button is on the **Access keys** tab. It is there only when we have turned the feature on. If it is missing, [create an access key](/docs/object-storage/access-keys/) instead.

## What temporary credentials can do

You choose three limits when you create them: the buckets, a key prefix and the permissions.

**Scope**
: **All buckets on this account** covers every bucket whose name starts with your prefix, such as `u7-`, including buckets you create later. One bucket covers that bucket only, and every other bucket refuses the credentials.

**Key prefix**
: Optional. The credentials reach only keys that start with it. With `photos/2026/` they read `photos/2026/jan/a.jpg` and refuse `photos/2025/a.jpg`. End a folder's prefix with a slash. Without the slash, `photos/2026` also matches `photos/2026-old/a.jpg`. When a request reads or writes an object, upper and lower case are not told apart: `photos/` also reaches `Photos/a.jpg`. A listing does tell them apart. Do not use a prefix to separate keys whose names differ only in case.

**Permissions**
: **Read only** lists and downloads objects, and lists their versions and tags. **Read and write** also uploads, copies and deletes objects, including multipart uploads and old versions that Object Lock does not protect, and adds and removes object tags.

They cannot do more than an access key of the same permissions. Temporary credentials never:

- create or delete a bucket,
- read or change a bucket's settings, such as its versioning, CORS rules, lifecycle rules or policy,
- read or change an object's ACL, retention or legal hold, or
- ask for more credentials.

A request that tries any of these answers `403` `AccessDenied`. An access key can read a bucket's settings; temporary credentials cannot.

**Lifetime**
: From 900 seconds (15 minutes) to 43200 seconds (12 hours). The dashboard offers **15 minutes**, **1 hour** and **12 hours**. The API takes any number between.

Temporary credentials work at once, with no wait for them to reach storage. They stop working at the **Expires** time, and nothing can end them sooner, so pick the shortest time the work needs.

Requests made with them are counted and billed to the service like requests made with an access key ([Usage and billing](/docs/object-storage/usage-and-billing/)).

## Create temporary credentials

1. Open the service and select the **Access keys** tab.
2. Select **Temporary credentials…**.
3. Under **Scope**, keep **All buckets on this account** or choose one bucket.
4. In **Key prefix (optional)**, type a prefix such as `photos/2026/`, or leave it empty to cover every key. A prefix has at most 256 bytes. It cannot contain `*`, `?`, `$` or a backslash, and it cannot start with a slash.
5. Under **Permissions**, choose **Read only** or **Read and write**. **Read only** is selected first.
6. Under **How long**, choose **15 minutes**, **1 hour** or **12 hours**. **1 hour** is selected first.
7. Select **Create credentials**.

## Save the credentials

The dialog now shows the credentials, under **Save these credentials now**. This is the only time the dashboard or the API shows the secret access key and the session token. We do not keep either.

**Access key ID**
: Starts with `ASIA`.

**Secret access key** and **Session token**
: Hidden at first. Select the eye icon beside one to show it, or copy it without showing it.

**Expires**
: When the credentials stop working, in your time zone, with how long is left.

**Endpoint** and **Region**
: Where to send requests. For a bucket in another region, use that region's endpoint.

**Scope**, **Key prefix** and **Permissions**
: What you chose.

To copy the values:

- **Copy all** copies every field, the secret and the token included, as lines of text.
- The copy button beside a field copies that value.
- **Environment variables** holds the four `export` lines the AWS CLI and the AWS SDKs read. **AWS CLI** holds a command that lists what the credentials cover.

Select **I have saved them** when you have stored the values where your app can read them.

## Use the credentials

Every request carries the session token as well as the key ID and the secret. Send requests to the endpoint with path-style addressing, as for an access key ([Connect an S3 client](/docs/object-storage/connect-an-s3-client/)).

### AWS CLI

Paste the **Environment variables** block into your shell, then run a command with the endpoint:

```bash
export AWS_ACCESS_KEY_ID=ASIAEXAMPLE0000000000
export AWS_SECRET_ACCESS_KEY=ExampleSecretAccessKey000000000000000000
export AWS_SESSION_TOKEN=ExampleSessionToken
export AWS_DEFAULT_REGION=fra

aws s3 ls s3://u7-assets/photos/2026/ --endpoint-url https://s3.fra.coritan.com:7337
aws s3 cp ./report.pdf s3://u7-assets/photos/2026/report.pdf --endpoint-url https://s3.fra.coritan.com:7337
```

### Python

```python
import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.fra.coritan.com:7337",
    region_name="fra",
    aws_access_key_id="ASIAEXAMPLE0000000000",
    aws_secret_access_key="ExampleSecretAccessKey000000000000000000",
    aws_session_token="ExampleSessionToken",
    config=Config(s3={"addressing_style": "path"}),
)
print(s3.list_objects_v2(Bucket="u7-assets", Prefix="photos/2026/")["KeyCount"])
```

### Listing with a prefix

Credentials limited to a prefix can list only that prefix. Name it in every listing, or a longer prefix under it:

- `aws s3 ls s3://u7-assets/photos/2026/` works. `aws s3 ls s3://u7-assets/` is refused, because it would show keys outside the prefix.
- `aws s3 ls` with no bucket lists the buckets the credentials cover, and shows none when they have a prefix.
- A tool that checks a bucket exists before it uses it, with a `HEAD` request on the bucket, is refused. Turn that check off, as `no_check_bucket = true` does in rclone.

## Result

The credentials list, read and write what you chose, at the endpoint, until the **Expires** time. After it, every request is refused with `InvalidAccessKeyId`, and you create new credentials.

## Troubleshooting

`InvalidAccessKeyId`
: The credentials have expired, or the request left out the session token or sent a wrong one. Check that your client sends the token with the key ID and the secret, and create new credentials if the time has passed.

`AccessDenied`
: The request is outside what you chose: another bucket, a key outside the prefix, a write with **Read only** credentials, or a call such as creating a bucket or reading a bucket's settings. A listing that does not name the prefix is refused too.

The **Temporary credentials…** button is missing
: The service is not `active`, or we have not turned the feature on. [Create an access key](/docs/object-storage/access-keys/) instead.

`Temporary credentials are not available yet. Create an access key instead.`
: We have not turned the feature on. Use an access key.

`Temporary credentials are not ready in this region yet. Try again in a few minutes.`
: We turned the feature on and the region's storage servers have not picked it up yet. Try again in a few minutes.

`A prefix cannot contain *, ?, $ or a backslash`
: Remove the character. A prefix is plain text, and these characters have a meaning in the permissions the credentials carry, so a key that holds one cannot be named by a prefix.

`Too many requests for this action. Try again later.`
: One account may create 120 sets of temporary credentials an hour. Wait, or reuse a set that has not expired.

An AWS tool's `assume-role` call is refused
: The credentials come from this page and the API below. Calls such as `aws sts assume-role` against the endpoint answer `AccessDenied`.

## Related

- [Create and revoke access keys](/docs/object-storage/access-keys/)
- [Connect an S3 client](/docs/object-storage/connect-an-s3-client/)
- [Object Storage limits](/docs/object-storage/limits/)
- [Troubleshoot Object Storage](/docs/object-storage/troubleshooting/)

## With the API

Each request takes the service ID. A service that is not Object Storage on your account answers `404` with `Object storage service not found`.

### Check that they are available

[`GET /api/v1/client/object-storage/{service_id}/credentials`](/docs/api/reference/client/object-storage/object-storage/#op-get-api-v1-client-object-storage-service-id-credentials) says whether you can create temporary credentials and which limits apply:

```bash
curl https://api.coritan.com/api/v1/client/object-storage/1207/credentials \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

```json
{
  "enabled": true,
  "modes": ["read", "read_write"],
  "min_expires_in": 900,
  "max_expires_in": 43200,
  "default_expires_in": 3600,
  "max_prefix_bytes": 256
}
```

`enabled` is `false` until we turn the feature on. The dashboard shows **Temporary credentials…** only when it is `true`.

### Create credentials

[`POST /api/v1/client/object-storage/{service_id}/credentials`](/docs/api/reference/client/object-storage/object-storage/#op-post-api-v1-client-object-storage-service-id-credentials) takes:

`mode`
: Required. `read` or `read_write`.

`bucket_id`
: Optional. The `id` of one of the service's buckets. Without it, the credentials cover every bucket on your account.

`prefix`
: Optional. Keys must start with it. At most 256 bytes. Without it, the credentials cover every key.

`expires_in`
: Optional. Seconds until they expire, from 900 to 43200. The default is 3600.

```bash
curl -X POST https://api.coritan.com/api/v1/client/object-storage/1207/credentials \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode": "read", "bucket_id": 31, "prefix": "photos/2026/", "expires_in": 1800}'
```

It answers `201`:

```json
{
  "access_key_id": "ASIAEXAMPLE0000000000",
  "secret_access_key": "ExampleSecretAccessKey000000000000000000",
  "session_token": "ExampleSessionToken",
  "expiration": "2026-10-09T10:30:00Z",
  "endpoint": "https://s3.fra.coritan.com:7337",
  "region": "fra",
  "bucket": "u7-assets",
  "prefix": "photos/2026/",
  "mode": "read"
}
```

`secret_access_key` and `session_token` appear in this response and never again. `expiration` is in UTC. `bucket` is `null` for credentials that cover every bucket. `endpoint` and `region` are those of the bucket, or of the service's home region when the credentials cover every bucket.

| Status | `detail` | Cause |
| --- | --- | --- |
| `404` | `Bucket not found` | `bucket_id` is not one of the service's buckets. |
| `409` | `This service is suspended; it can be changed once it is active` | The service is not `active`. The message names its status. |
| `409` | `Create a bucket first. A service gets its region from its first bucket.` | The service has no region and no bucket yet. |
| `422` | `A prefix cannot contain *, ?, $ or a backslash` | The prefix holds one of those characters. |
| `422` | `A prefix does not start with a slash` | The prefix starts with `/`. |
| `422` | `A prefix is at most 256 bytes` | The prefix is longer. |
| `422` | a list of fields | `mode` is not `read` or `read_write`, or `expires_in` is outside 900 to 43200. |
| `429` | `detail.message` is `Too many requests for this action. Try again later.` | The account asked for more than 120 sets in an hour. The `Retry-After` header says how many seconds to wait. |
| `503` | `Temporary credentials are not available yet. Create an access key instead.` | We have not turned the feature on. |
| `503` | `Temporary credentials are not ready in this region yet. Try again in a few minutes.` | The region's storage servers have not picked up the feature. |
| `502` | `Storage would not issue temporary credentials. Try again in a minute.` | The region's storage servers refused the request. Try again. |
| `502` | `Storage did not answer. Try again in a minute.` | The region's storage servers did not answer in time. Try again. |

## API

- `GET /api/v1/client/object-storage/{service_id}/credentials`: Whether temporary credentials can be created for this service, and the limits they follow (https://www.coritan.com/docs/api/reference/client/object-storage/object-storage/#op-get-api-v1-client-object-storage-service-id-credentials)
- `POST /api/v1/client/object-storage/{service_id}/credentials`: Create temporary credentials (https://www.coritan.com/docs/api/reference/client/object-storage/object-storage/#op-post-api-v1-client-object-storage-service-id-credentials)
