
# keenauth_directory_token

The `keenauth_directory_token` resource creates a SCIM bearer token of a directory for the identity provider that provisions users and groups to it. The provider keeps the token in state only encrypted to an RSA public key that you give it.

```terraform
resource "keenauth_directory_token" "okta" {
  directory_id    = keenauth_directory.acme_okta.id
  label           = "Okta"
  expires_in_days = 180
  public_key      = file("${path.module}/scim-token-key.pub.pem")

  lifecycle {
    create_before_destroy = true
  }
}

output "okta_scim_token_encrypted" {
  value = keenauth_directory_token.okta.encrypted_token
}
```

## The token is never stored in plain text

The API returns a SCIM token once, in the response that creates it, and no endpoint can read it afterwards. The provider encrypts the token with your public key (RSA-OAEP with SHA-256, MGF1 SHA-256 and an empty label) and writes only the base64 ciphertext to `encrypted_token`. The plain token never reaches state, a plan file, an output or a log. Only the holder of the private key can decrypt it, so a leaked state file does not leak the token.

Create the key pair once, outside OpenTofu, and keep the private key out of your configuration:

```shell
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out scim-token-key.pem
openssl pkey -in scim-token-key.pem -pubout -out scim-token-key.pub.pem
```

After `tofu apply`, decrypt the token and give it to the identity provider:

```shell
tofu output -raw okta_scim_token_encrypted | base64 -d | \
  openssl pkeyutl -decrypt -inkey scim-token-key.pem \
    -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256
```

`public_key` must be a PEM-encoded RSA public key (`PUBLIC KEY` or `RSA PUBLIC KEY`) of at least 2048 bits. A private key or a smaller key is rejected at plan time. If the provider cannot deliver a token, it revokes the token at once and the apply fails, so no valid token exists that nobody holds.

## Create and revoke only

A token cannot be changed. Every argument (`directory_id`, `label`, `expires_in_days`, `public_key`) creates a new token when you change it, and the old token is revoked. Destroying the resource revokes the token.

A token that was revoked outside the provider, or that expired, is removed from state on the next refresh, and the next apply creates a new one. Deleting the directory deletes its tokens.

## Rotation

A directory has at most 2 valid tokens; a third one is rejected with `409`. That is enough to rotate without downtime: with `create_before_destroy = true` the new token is created before the old one is revoked. Give the new token to the identity provider in the same change window.

## Arguments

- `label` is 1 to 100 characters, without control characters and without leading or trailing whitespace. The API default is `Token`.
- `expires_in_days` is 30 to 730. The API default is 365.
- `encrypted_token`, `created_at`, `expires_at` and `id` are read-only.

## Import

The resource cannot be imported: the value of an existing token can never be read again, so an imported token could not be delivered. Revoke an old token with `keenauth directories tokens delete <directory_id> <token_id>` and let the provider create a new one.
