Manage workforce (Identity Center) users headlessly (M2M)¶
Manage your organization’s workforce (Identity Center) users from a backend service with no interactive login — using only a service access key (AK/SK) and STS. The pattern is AWS-faithful: your key assumes a role, and the role’s temporary credentials carry the permission to manage IdC users.
AK/SK → assume-role → ASIA temp creds → FGAI-HMAC + X-FGAI-Security-Token
→ /identity/v1/organizations/{orgId}/identity-center/users…
Why a role (and not your key directly)? Workforce-user management is authorized
on every call against identitycenter:User:{verb}. That permission is granted to a
role which lives in your organization’s management account; you assume the
role to act with it. This keeps your long-lived service key permission-light and
follows the same shape as AWS IAM + STS.
Prerequisites: a service access key (see Integrate an external app with AK/SK) and the ability to sign requests with FGAI-HMAC-SHA256 (see IAM roles and STS AssumeRole). All calls below are one signed HTTPS request to https://api.flexgalaxy.ai (or http://api.dev.fgai.test in local dev).
The role lives in the management account¶
The WorkforceAdminRole always lives in your organization’s management account
({mgmtAccountId}), because that is where the Identity Center directory is anchored.
Its FRN is therefore frn:{mgmtAccountId}:iam:role/WorkforceAdminRole and its
permission policy grants identitycenter:User:* on
frn:{mgmtAccountId}:identitycenter:user/*. Which path you follow depends on where
your service principal lives:
Path |
Your service principal is in… |
You get the role by… |
|---|---|---|
Primary — platform-seeded (external integrator) |
your own tenant account (not the management account) |
the platform seeds the role in the management account for you; its trust admits your principal’s FRN across accounts and requires an |
Secondary — self-authored (management-account only) |
the management account itself |
you author the role, its managed policy, and the attachment yourself, then assume it. |
The primary path is the norm for an external integrator: a service key is pinned to its own account, so it cannot author a role in the management account — the platform seeds that role. The self-author path is available only when your principal already lives in the management account.
Two load-bearing constraints¶
Read these first — getting either wrong yields a silent 403 IMPLICIT_DENY. They
hold on both paths (the platform-seeded role already satisfies them).
The permission is granted with a MANAGED policy, attached to the role. A role’s inline policy is not honored for this path. The grant is a customer-managed
iam-policyattached withPOST …/roles/{roleId}/policies.The policy
Resourcemust match the Identity Center user FRN. It must befrn:{mgmtAccountId}:identitycenter:user/*(or*). A narrower or wrongResourcewill not match and the call is denied.
Primary path — assume the platform-seeded role (external integrator)¶
Your service principal lives in your own tenant account. During onboarding the
platform seeds the WorkforceAdminRole in your organization’s management account,
with a trust policy that admits your principal FRN across accounts and requires
a shared-secret sts:ExternalId. You do not author anything — you assume and act.
What onboarding gives you:
the role FRN —
frn:{mgmtAccountId}:iam:role/WorkforceAdminRolethe
externalIdshared secret for the trust conditionyour
{orgId}(and its{mgmtAccountId})
1. Assume the role → temporary credentials¶
POST /identity/v1/sts/assume-role — signed with your static service key
(AKIA), even though the role is in a different (management) account. This is a
cross-account assume-role; the role’s trust policy is the gate.
{
"roleFrn": "frn:{mgmtAccountId}:iam:role/WorkforceAdminRole",
"roleSessionName": "workforce-batch-42",
"durationSeconds": 3600,
"externalId": "shared-secret-xyz"
}
The response returns ASIA… credentials (accessKeyId, secretAccessKey,
sessionToken, expiration). durationSeconds is clamped to
[900, role.maxSessionDuration]. A wrong or missing externalId returns 403
with no credentials.
2. Manage workforce users with the temporary credentials¶
Sign each call with the ASIA credentials (FGAI-HMAC-SHA256) and add the
X-FGAI-Security-Token header set to the sessionToken.
… /identity/v1/organizations/{orgId}/identity-center/users
Method |
Path |
Purpose |
|---|---|---|
|
|
List workforce users |
|
|
Invite a workforce user |
|
|
Read a workforce user |
|
|
Update a workforce user |
|
|
Disable / enable |
|
|
Reset login credential |
|
|
Remove a workforce user |
Each operation is checked against identitycenter:User:{verb}; with the seeded
role’s managed policy, the check returns ALLOW.
How to find your mgmtAccountId¶
The role FRN, the policy Resource, and the {orgId} path all point at your
organization’s management account. Resolve it from the organization: read your
organization (GET /organizations/v1/{orgId}) — its management
account id is the mgmtAccountId. For a self-author (management-account) principal
this is simply your own account id.
Long-running jobs: session duration and re-assume¶
Assumed-role credentials are short-lived — durationSeconds, clamped to
[900, role.maxSessionDuration] (default 3600). A long headless batch must
re-assume the role before the current expiration and continue signing with the
fresh ASIA credentials. Refresh a little ahead of expiry (e.g. at 80% of the
lifetime) rather than waiting for a 401.
Failures¶
Missing/invalid signature →
401.Role missing or its trust policy denies you (wrong principal or wrong
externalId) →403(indistinguishable, so a caller cannot probe for roles in another account), with no credentials returned.Permission not granted (no managed policy attached, or
Resourcedoesn’t match) →403on theidentity-center/userscall.
See also¶
Integrate an external app with AK/SK — FGAI-HMAC signing.
IAM roles and STS AssumeRole — roles, trust policies, STS reference.
[FRN format](https://docs.flexgalaxy.ai/dev/dotid/frn-format/)