Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion reference/operations-api/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ Detailed documentation: [JWT Authentication](../security/jwt-authentication.md)

### `create_authentication_tokens`

Does not require prior authentication. Returns `operation_token` (short-lived JWT) and `refresh_token` (long-lived JWT).
Does not require prior authentication when called with `username`/`password`. Returns `operation_token` (short-lived JWT) and `refresh_token` (long-lived JWT).

```json
{
Expand All @@ -549,6 +549,17 @@ Does not require prior authentication. Returns `operation_token` (short-lived JW
}
```

With `role` as an inline role object, instead mints a single **scoped token** whose bearer is limited to the embedded permissions — requires an authenticated `super_user` caller; `username` is attribution only and must not name an existing user (defaults to `scoped:<minter>`); no refresh token is issued and the token cannot be revoked before expiry. See [JWT Authentication / Scoped Tokens](../security/jwt-authentication.md#scoped-tokens-inline-role).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When documenting behavior changes to an existing surface (such as the new inline role parameter for create_authentication_tokens), please use the <VersionBadge type="changed" version="v5.2.0" /> format as prescribed in the repository's guidelines.

Suggested change
With `role` as an inline role object, instead mints a single **scoped token** whose bearer is limited to the embedded permissions — requires an authenticated `super_user` caller; `username` is attribution only and must not name an existing user (defaults to `scoped:<minter>`); no refresh token is issued and the token cannot be revoked before expiry. See [JWT Authentication / Scoped Tokens](../security/jwt-authentication.md#scoped-tokens-inline-role).
With `role` as an inline role object <VersionBadge type="changed" version="v5.2.0" />, instead mints a single **scoped token** whose bearer is limited to the embedded permissions — requires an authenticated `super_user` caller; `username` is attribution only and must not name an existing user (defaults to `scoped:<minter>`); no refresh token is issued and the token cannot be revoked before expiry. See [JWT Authentication / Scoped Tokens](../security/jwt-authentication.md#scoped-tokens-inline-role).
References
  1. Use the <VersionBadge type="changed" version="vX.Y.0" /> format when documenting behavior changes to existing surface, as prescribed in the repository's guidelines.


```json
{
"operation": "create_authentication_tokens",
"username": "reporting-service",
"role": { "permission": { "operations": ["read_only"] } },
"expires_in": "7d"
}
```

### `refresh_operation_token`

Creates a new operation token from an existing refresh token.
Expand Down
43 changes: 43 additions & 0 deletions reference/security/jwt-authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,49 @@ Response:

When both tokens have expired, call `create_authentication_tokens` again with your username and password.

## Scoped Tokens (Inline Role)

Available since: v5.2.0

A super user can mint a **scoped token**: a single JWT whose permissions are embedded in the token itself, so the bearer needs no pre-existing user or role record. This is useful for handing a limited credential (for example, read-only access) to an external service or script without provisioning it in `hdb_user`.

Pass `role` as an inline role-shaped object (the same `permission` structure used by [`add_role`](../users-and-roles/overview.md), including the `operations` allowlist). The request must be authenticated as a `super_user`; no `password` may be included:

```json
{
"operation": "create_authentication_tokens",
"username": "reporting-service",
"role": {
"permission": {
"operations": ["read_only"],
"dev": {
"tables": {
"dog": { "read": true, "insert": false, "update": false, "delete": false, "attribute_permissions": [] }
}
}
}
},
"expires_in": "7d"
}
```

Response:

```json
{
"operation_token": "<jwt-scoped-token>"
}
```

Behavior and constraints:

- **`username` is attribution only, and must not name an existing user.** It appears in audit logs and `user_info` for requests made with the token; a name that collides with a real `hdb_user` is rejected at mint. It defaults to `scoped:<minting user>`.
- **Permissions are enforced as embedded.** The `operations` allowlist limits which Operations API operations the bearer can call (including `sql`). Application/REST endpoints are governed by the embedded database/table permissions only — a token meant to be read-only on REST must set restrictive table permissions, not just a read-only `operations` list. `super_user` and `cluster_user` are always forced to `false` in the embedded role.
- **No refresh token is issued**, and no user record is created or modified.
- **Scoped tokens cannot be revoked before they expire.** They are not tied to a user row, so dropping or altering users has no effect on them; only expiry (or rotating the instance's JWT keys, which invalidates _all_ tokens) ends their validity. Choose `expires_in` accordingly — prefer short lifetimes.
- The permission object is validated at mint time (unknown operations, malformed shapes, and references to nonexistent databases/tables are rejected), and the resulting token must fit in an `Authorization` header (12KB limit).
- In mixed-version clusters, only nodes running a version with scoped-token support accept these tokens; older nodes reject them with a 401.

## Issuing Tokens from a Custom Resource

Custom Resources can mint tokens programmatically by invoking the same operations via [`server.operation()`](../http/api.md#serveroperationoperation-context-authorize). This is useful when you want a Resource-style endpoint (e.g., `POST /IssueTokens`) instead of (or in addition to) the raw Operations API.
Expand Down