Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

gRPC Authentication

Login

Authenticate with email and password to get a JWT token. Login is rate-limited — after too many failed attempts for an email, further attempts are temporarily blocked (configurable via max_login_attempts and login_lockout_seconds in crap.toml).

grpcurl -plaintext -d '{
    "collection": "users",
    "email": "admin@example.com",
    "password": "secret123"
}' localhost:50051 crap.ContentAPI/Login

The response contains a token and the user document.

Bearer Token

Pass the token via the authorization metadata header:

grpcurl -plaintext \
    -H "authorization: Bearer eyJhbGciOi..." \
    -d '{"collection": "posts"}' \
    localhost:50051 crap.ContentAPI/Find

The token is extracted from the authorization metadata and validated. The authenticated user is available to access control functions.

Get Current User

Use the Me RPC to validate a token and get the user:

grpcurl -plaintext -d '{
    "token": "eyJhbGciOi..."
}' localhost:50051 crap.ContentAPI/Me

Token Expiry

Tokens expire after token_expiry seconds (default: 7200 = 2 hours). Configurable globally in crap.toml or per auth collection.

Security

  • Rate limiting — per-email tracking. After max_login_attempts (default: 5) failures, the email is locked out for login_lockout_seconds (default: 300). Per-IP rate limiting (max_ip_login_attempts in [auth]) provides additional protection against credential stuffing across multiple accounts.
  • Timing safety — login always performs a full Argon2id hash comparison, even for non-existent users, preventing timing-based email enumeration.
  • JWT persistence — when no secret is set in crap.toml, an auto-generated secret is persisted to data/.jwt_secret so tokens survive server restarts.
  • Account locking — when a user’s _locked field is truthy, all authenticated requests (including Me) are rejected with unauthenticated status. This takes effect immediately, even for valid unexpired tokens.

Creating Users via gRPC

Include password in the data field of a Create request:

grpcurl -plaintext -d '{
    "collection": "users",
    "data": {
        "email": "new@example.com",
        "password": "secret123",
        "name": "New User",
        "role": "editor"
    }
}' localhost:50051 crap.ContentAPI/Create

The password field is extracted, hashed with Argon2id, and stored separately. It never appears in the response.

Updating Passwords

Include password in the data field of an Update request:

grpcurl -plaintext -d '{
    "collection": "users",
    "id": "abc123",
    "data": { "password": "new-password" }
}' localhost:50051 crap.ContentAPI/Update

If password is omitted, the existing password is kept.