accessRequests
Access requests let members ask for specific roles instead of asking an administrator to bind them by hand.
Access requests let members ask for specific roles instead of asking an administrator to bind them by hand. A member names up to 20 roles with a justification and an optional duration; a reviewer approves or denies, and approval creates the bindings under the reviewer's own grant authority, so a reviewer can never grant more than they could bind directly.
Request lifecycle
A request starts pending and ends in exactly one of approved, denied, cancelled (by the requester, or when
the requester is offboarded or deleted), or expired. Two times matter:
- How long a request waits. The request's
expiresAtis when a pending request lapses:accessRequests.lifetimeMsafter it was made (seven days by default; a deployment option between one minute and 365 days). A lapsed request is reported asexpiredat once and marked so in storage by the purge worker (iam.purgeDeleted()). - How long the access lasts.
durationSeconds(at least 60, at mostaccessRequests.maxDurationSeconds, 90 days by default) sets the end of the granted bindings, counted from approval. The request records it asgrantExpiresAt. Without a duration the bindings are permanent.
Approved bindings are ordinary role bindings tagged with accessRequestId. They end at grantExpiresAt, or when an
administrator removes them with bindings.delete; the request itself only
records the decision. No notifications are sent: reviewers find work with list({ status: 'pending' }).
Use access requests for ad hoc roles. For a curated bundle of roles and groups with designated approvers, use requestable access packages instead.
| Method | What it does | Access |
|---|---|---|
approve | Approves a pending request, binding each requested role to the requester under your own grant authority. | Credential |
cancel | Withdraws one of your own pending requests. | Credential |
create | Asks for one or more roles for yourself, optionally for a limited time. | Credential |
deny | Refuses a pending request, with an optional note for the requester. | Credential |
get | Returns one request. | Credential |
list | Lists the tenant's requests, newest first, optionally by status or requester. | Credential |
listMine | Lists your own requests, newest first, optionally by status. | Credential |
approve
Approves a pending request, binding each requested role to the requester under your own grant authority.
Used inTemporary access
- Permission:
iam:access-requests:reviewon the request, plusiam:bindings:createon each requested role and a grant authority, exactly asbindings.createrequires. - Audited as:
iam:access-requests:review, plusaccess-request:approvewith the requester, roles, binding IDs, andgrantExpiresAt. - Errors:
INVALID_TRANSITION(409) when the request is no longer pending, including when it has lapsed;ACCESS_DENIEDwhen you are the requester or cannot bind one of the roles;INVALID_IDENTITYwhen the requester is not active;NOT_FOUNDwhen the request, the requester, or a role is gone;INVALID_INPUTfor adurationSecondsout of range;GRANT_AUTHORITY_REQUIREDwithout a grant authority;SOD_CONFLICTwhen the roles would create a separation-of-duties conflict;INVARIANT_VIOLATIONwhen they would break an enforced invariant.
durationSeconds overrides the duration the requester asked for; the bindings end that long after approval. If the
requester already holds one of the roles through a binding under your authority, that binding is reused and its end
replaced by the approved one (removed, when no duration applies). The optional note is stored on the request.
await iam.api.accessRequests.approve(reviewerCredential, {
tenantId,
requestId,
durationSeconds: 8 * 60 * 60, // one working day instead of the week they asked for
note: 'Approved for the incident review.',
});Prop
Type
A AccessRequest object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/accessRequests/approve" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"requestId": "<requestId>"
}'iam.api.accessRequests.approve(
credential: CredentialInput,
input: {
tenantId: string;
requestId: string;
durationSeconds?: number;
note?: string;
},
): Promise<AccessRequest>cancel
Withdraws one of your own pending requests.
- Permission:
iam:access-requests:createon the request, and you must be the requester. - Audited as:
iam:access-requests:create. - Errors:
ACCESS_DENIEDwhen the request is someone else's;INVALID_TRANSITIONwhen it is no longer pending;NOT_FOUNDwhen it is not in this tenant.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/accessRequests/cancel" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"requestId": "<requestId>"
}'iam.api.accessRequests.cancel(
credential: CredentialInput,
input: { tenantId: string; requestId: string },
): Promise<{
status: string;
reviewedAt: number;
requesterId: string;
roleIds: string[];
justification?: string;
durationSeconds?: number;
createdAt: number;
expiresAt: number;
reviewerId?: string;
note?: string;
bindingIds?: string[];
grantExpiresAt?: number;
id: string;
tenantId: string;
uniqueKey?: string;
}>create
Asks for one or more roles for yourself, optionally for a limited time.
Used inTemporary access
- Permission:
iam:access-requests:createon the tenant, from an ordinary session of that tenant. - Audited as:
iam:access-requests:create. - Errors:
INVALID_INPUTfrom a role session or another tenant's session, for zero or more than 20 roles, or adurationSecondsout of range;PROTECTED_RESOURCEfor an owner role;NOT_FOUNDwhen a role is not in this tenant;CONFLICTwhen a pending request for the same set of roles exists;TOO_MANY_REQUESTS(429) when you already have 20 pending requests;TENANT_INACTIVEwhen the tenant is not active.
Nothing is granted until a reviewer approves. justification (up to 2048 characters) is shown to reviewers. Grant
iam:access-requests:create to every member, for example through a group everyone belongs to, and
iam:access-requests:review to the people who decide.
const request = await iam.api.accessRequests.create(memberCredential, {
tenantId,
roleIds: [supportAdminRole.id],
justification: 'Covering the support rotation this week',
durationSeconds: 7 * 24 * 60 * 60,
});
// request.status === 'pending'; request.expiresAt is when it lapses if nobody decidesProp
Type
A AccessRequest object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/accessRequests/create" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"roleIds": [
"<roleId>"
]
}'iam.api.accessRequests.create(
credential: CredentialInput,
input: {
tenantId: string;
roleIds: string[];
justification?: string;
durationSeconds?: number;
},
): Promise<AccessRequest>deny
Refuses a pending request, with an optional note for the requester.
- Permission:
iam:access-requests:reviewon the request. - Audited as:
iam:access-requests:review, plusaccess-request:denywith the requester and roles. - Errors:
INVALID_TRANSITIONwhen the request is no longer pending;NOT_FOUNDwhen it is not in this tenant.
Prop
Type
A AccessRequest object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/accessRequests/deny" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"requestId": "<requestId>"
}'iam.api.accessRequests.deny(
credential: CredentialInput,
input: { tenantId: string; requestId: string; note?: string },
): Promise<AccessRequest>get
Returns one request.
- Permission:
iam:access-requests:readon the request. - Audited as:
iam:access-requests:read. - Errors:
NOT_FOUNDwhen the request is not in this tenant.
A pending request past its lifetime is returned as expired.
Prop
Type
A AccessRequest object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/accessRequests/get" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"requestId": "<requestId>"
}'iam.api.accessRequests.get(
credential: CredentialInput,
input: { tenantId: string; requestId: string },
): Promise<AccessRequest>list
Lists the tenant's requests, newest first, optionally by status or requester.
- Permission:
iam:access-requests:readon the tenant. - Audited as:
iam:access-requests:read. - Errors:
INVALID_INPUTfor an unknownstatus.
The status filter matches the stored status, so until the purge worker runs, status: 'pending' can include
lapsed requests, which are reported as expired.
Prop
Type
An array of AccessRequest.
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/accessRequests/list" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.accessRequests.list(
credential: CredentialInput,
input: { tenantId: string; status?: AccessRequestStatus; requesterId?: string },
): Promise<AccessRequest[]>listMine
Lists your own requests, newest first, optionally by status.
- Permission:
iam:access-requests:createon the tenant, so anyone who may ask can see their own requests. - Audited as:
iam:access-requests:create. - Errors:
INVALID_INPUTfor an unknownstatus.
Prop
Type
An array of AccessRequest.
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/accessRequests/listMine" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.accessRequests.listMine(
credential: CredentialInput,
input: { tenantId: string; status?: AccessRequestStatus },
): Promise<AccessRequest[]>Better IAM is created by Sean Filimon
Last updated