IAM roles and STS AssumeRole¶
DotID models roles the same way AWS IAM does: a role is an assumable identity in an account with a trust policy (who may assume it) and attached permission policies (what it may do). A caller assumes a role through STS AssumeRole and receives short-lived credentials that act with the role’s permissions in the role’s account. This is the mechanism behind cross-account access.
Authentication¶
Role management and STS are self-managed by the account admin. Sign requests with an account service-user access key using FGAI-HMAC-SHA256 (see [CLI & service authentication](https://docs.flexgalaxy.ai/dev/dotid/cli-authentication/)); a bearer JWT is also accepted. Your credential is pinned to one account — you manage roles only in that account.
Base URL: https://api.flexgalaxy.ai (production) or http://api.dev.fgai.test (local dev).
Roles¶
Method |
Path |
Purpose |
|---|---|---|
|
|
Create a role |
|
|
List roles |
|
|
Get a role |
|
|
Update trust policy / description / max session |
|
|
Delete a role |
|
|
Attach a permission policy |
|
|
List attached policies |
|
|
Detach a policy |
Create a role¶
The trustPolicy is required and answers “who may assume me”. name is required;
description, path, and maxSessionDuration (seconds) are optional.
{
"name": "DeviceReader",
"description": "Read-only device access, assumable by the ops tooling account.",
"maxSessionDuration": 3600,
"trustPolicy": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Account": ["acc-0a1b2c3d4e5f"] },
"Action": "sts:AssumeRole"
}
]
}
}
The response is the created role, including its id:
{
"id": "8b2f0a3e-1c4d-4e6f-9a01-2b3c4d5e6f70",
"accountId": "11111111-1111-1111-1111-111111111111",
"name": "DeviceReader",
"trustPolicy": { "…": "…" },
"maxSessionDuration": 3600,
"version": 1,
"createdAt": "2026-07-07T09:00:00Z"
}
Trust policy¶
Each statement admits a caller when Effect is Allow, Action includes
sts:AssumeRole, the Principal block matches the caller, and every Condition
is satisfied. Evaluation is fail-closed: with no matching Allow the caller is
denied, and a matching Deny always wins.
Principal accepts:
Form |
Meaning |
|---|---|
|
Any caller. |
|
Any principal in that account. |
|
A specific principal, by [FRN](https://docs.flexgalaxy.ai/dev/dotid/frn-format/). |
|
A whole account (account-form FRN). |
Optionally require a shared secret with an sts:ExternalId condition:
{
"Effect": "Allow",
"Principal": { "Account": ["acc-0a1b2c3d4e5f"] },
"Action": "sts:AssumeRole",
"Condition": { "StringEquals": { "sts:ExternalId": "shared-secret-xyz" } }
}
Attach a permission policy¶
Attach one of your account’s IAM policies by id to grant the role what it may do:
curl -fsS -X POST \
"{{ dotid_api_prod }}/identity/v1/accounts/$ACCOUNT_ID/roles/$ROLE_ID/policies" \
-H "Content-Type: application/json" \
-d '{ "policyId": "a1b2c3d4-…" }'
# + FGAI-HMAC-SHA256 signing headers
STS AssumeRole¶
Exchange your credential for temporary credentials scoped to a role.
Method |
Path |
Purpose |
|---|---|---|
|
|
Assume a role → temporary credentials |
Request¶
roleFrn and roleSessionName are required; durationSeconds and externalId
are optional. Pass externalId when the target role’s trust policy requires one.
{
"roleFrn": "frn:acc-target00acct:iam:role/DeviceReader",
"roleSessionName": "ops-tooling-run-42",
"durationSeconds": 3600,
"externalId": "shared-secret-xyz"
}
durationSeconds is clamped to [900, role.maxSessionDuration].
Response¶
{
"assumedRoleFrn": "frn:acc-target00acct:iam:role/DeviceReader",
"accountId": "22222222-2222-2222-2222-222222222222",
"roleSessionName": "ops-tooling-run-42",
"accessKeyId": "ASIA…",
"secretAccessKey": "…",
"sessionToken": "…",
"expiration": "2026-07-07T10:00:00Z"
}
The returned credentials are temporary (ASIA… key id). Use them to sign
subsequent requests with FGAI-HMAC-SHA256, adding the session token as the
X-FGAI-Security-Token header. Requests signed with these credentials act in the
role’s account with the role’s permissions — so authorization decisions for the
session resolve from the role’s attached policies (see
Check authorization (PDP)).
Failures¶
A missing or invalid signature returns
401.If the role does not exist or its trust policy denies the caller, the call returns
403— the two cases are indistinguishable, so a caller cannot probe for roles in another account.
→ Manage workforce users¶
A common use of an assumed role is headless workforce (Identity Center) user
management: attach a managed policy granting identitycenter:User:* to a role,
assume it, and manage users in the organization Identity Center directory with the
temporary credentials — no interactive login. See the worked recipe in
Manage workforce (Identity Center) users headlessly (M2M).
See also¶
[FRN format](https://docs.flexgalaxy.ai/dev/dotid/frn-format/)
[Hierarchical access](https://docs.flexgalaxy.ai/dev/dotid/hierarchical-access/)