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 Login or RefreshToken.

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 WhoAmI after 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 Admin and Grant permissions rare.