User Administration
For hosted signup, sign-in, account recovery, and platform administration, see ShrikeDB Cloud.
The gRPC examples require the downloadable API definitions and SHRIKEDB_API_DIR setup. User administration is available when the server is built with the multi-tenant feature.
In the default single-tenant development mode, ShrikeDB uses an implicit system context and does not require user setup.
The identity API is gRPC package shrikedb.identity.v2.
It manages tenants, users, roles, policy documents, API keys, login, refresh tokens, and WhoAmI introspection.
Enable Multi-Tenant Identity
Use a supplied multi-tenant server package and enable authentication in its configuration. Obtain the initial administrator credential through your deployment’s provisioning procedure before running identity-management requests.
Start it with your normal server config. The main database gRPC endpoint is the same endpoint used for identity RPCs in these examples.
Administration Model
| Object | Purpose |
|---|---|
Tenant |
Top-level security boundary. Users, roles, API keys, and policy documents belong to a tenant. |
User |
Human or service principal. A user can have a password, API keys, or both. |
Role |
Named set of RBAC permissions assigned to users. |
Policy document |
Tenant ABAC policy stored as JSON and applied through the hot policy cache. |
API key |
Longer-lived service credential. The raw key is returned once and cannot be fetched later. |
JWT access token |
Short-lived bearer token returned by |
Admin-level identity RPCs require an authenticated principal with Admin or Grant permission on the tenant.
The exact bootstrap credential depends on how your deployment is packaged.
After bootstrap, use the least-privileged tenant admin role you can.
Create A Tenant
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d '{"slug":"acme","displayName":"Acme Analytics"}' \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/CreateTenant
The response includes tenantUid.
Save it:
export TENANT_UID=YOUR_RETURNED_TENANT_UID
Create Roles
A tenant admin role grants full authority inside one tenant:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "{
\"tenantUid\": {\"id\": ${TENANT_UID}},
\"name\": \"tenant-admin\",
\"permissions\": [
{
\"scope\": \"PERMISSION_SCOPE_TENANT\",
\"mode\": \"PERMISSION_MODE_ADMIN\"
}
]
}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/CreateRole
A read-oriented analyst role can be narrower:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "{
\"tenantUid\": {\"id\": ${TENANT_UID}},
\"name\": \"graph-analyst\",
\"permissions\": [
{
\"scope\": \"PERMISSION_SCOPE_GRAPH_NAMESPACE\",
\"mode\": \"PERMISSION_MODE_READ\",
\"namespace\": \"default\"
},
{
\"scope\": \"PERMISSION_SCOPE_SEMANTIC_PROFILE\",
\"mode\": \"PERMISSION_MODE_READ\",
\"namespace\": \"default\"
},
{
\"scope\": \"PERMISSION_SCOPE_ONTOLOGY_VIEW\",
\"mode\": \"PERMISSION_MODE_READ\",
\"namespace\": \"default\"
}
]
}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/CreateRole
Save returned role IDs:
export ANALYST_ROLE_UID=456
Create Users
Create a password-capable user:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "{
\"tenantUid\": {\"id\": ${TENANT_UID}},
\"username\": \"casey\",
\"password\": \"change-this-before-real-use\",
\"roleUids\": [{\"id\": ${ANALYST_ROLE_UID}}]
}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/CreateUser
Create an API-key-only service user by omitting password:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "{
\"tenantUid\": {\"id\": ${TENANT_UID}},
\"username\": \"frontend-bridge\",
\"roleUids\": [{\"id\": ${ANALYST_ROLE_UID}}]
}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/CreateUser
Login And Refresh
Login returns a short-lived JWT access token and a refresh token:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-d "{
\"tenantUid\": {\"id\": ${TENANT_UID}},
\"username\": \"casey\",
\"password\": \"change-this-before-real-use\"
}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/Login
Refresh rotates the refresh token. Store the new refresh token and discard the old one:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-d "{\"refreshToken\": \"${REFRESH_TOKEN}\"}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/RefreshToken
Create And Revoke API Keys
CreateApiKey returns rawKey exactly once.
Store it in your secret manager immediately.
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "{
\"userUid\": {\"id\": ${SERVICE_USER_UID}},
\"name\": \"frontend-bridge-prod\"
}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/CreateApiKey
Use the API key on requests:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "x-shrikedb-api-key: ${SHRIKEDB_API_KEY}" \
-d '{}' \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/WhoAmI
Revoke a key:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "{\"keyUid\": {\"id\": ${KEY_UID}}}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/RevokeApiKey
Inspect The Current Credential
WhoAmI is the safest first check when an authenticated call fails:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ACCESS_TOKEN}" \
-d '{}' \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/WhoAmI
It returns the user UID, tenant UID, auth method, and resolved permissions.
Suspend Or Reactivate Access
Suspend a user:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "{
\"userUid\": {\"id\": ${USER_UID}},
\"status\": \"suspended\"
}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/UpdateUserStatus
Suspend a tenant:
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "{
\"tenantUid\": {\"id\": ${TENANT_UID}},
\"suspend\": true
}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/SuspendTenant
Use status: "active" or suspend: false to reactivate.
Policy Documents
RBAC roles are usually enough for simple deployments. ABAC policy documents add conditional allow/deny rules over principal, resource, and environment attributes.
The SetPolicyDocument RPC accepts a JSON-encoded PolicyDocument value from the shrikedb-security policy model.
Keep tenant policies small, explicit, and versioned in your own config repository.
POLICY_JSON='{"statements":[]}'
REQUEST_JSON="$(jq -n \
--argjson tenant "${TENANT_UID}" \
--arg policy "${POLICY_JSON}" \
'{tenantUid:{id:$tenant}, policyJson:$policy}')"
grpcurl -plaintext \
-import-path "$SHRIKEDB_API_DIR" -proto shrikedb.identity.v2.proto \
-H "authorization: Bearer ${ADMIN_TOKEN}" \
-d "${REQUEST_JSON}" \
127.0.0.1:50251 shrikedb.identity.v2.IdentityService/SetPolicyDocument
The policyJson field is a string containing the policy document, not an inline object.
Practical Checklist
-
Use one tenant per security boundary.
-
Give service accounts API keys, not shared human passwords.
-
Store raw API keys and refresh tokens outside ShrikeDB config files and benchmark artifacts.
-
Prefer namespace-scoped read/write roles over tenant-wide admin roles.
-
Use
WhoAmIafter role or policy changes to confirm the resolved permission set. -
Suspend users before deleting external identity records, so audit history remains interpretable.
-
Revoke unused API keys during incident response and after operator handoff.
-
Keep
AdminandGrantpermissions rare.