> For the complete documentation index, see [llms.txt](https://docs.empe.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.empe.io/develop/wallet-server/security-considerations.md).

# Security Considerations

The service protects every non-public endpoint with OIDC Bearer-token authentication, role-based access control, per-tenant ownership checks, and global rate limiting. This page describes the security model so you can integrate against it safely.

## Authentication

Authenticated requests carry a standard OAuth 2.0 / OIDC access token in the HTTP `Authorization` header:

```bash
curl https://issuer.example.com/agent/dids \
  -H "Authorization: Bearer <access_token>"
```

* **Scheme:** `Authorization: Bearer <JWT>` (the OpenAPI document marks protected operations with the standard bearer security scheme).
* **Signing algorithm:** `RS256`.
* **Key resolution:** the token's `kid` header selects the public verification key, which is fetched from the OIDC provider's JWKS endpoint configured in `OIDC_JWKS_URL`. Keys are cached for 10 minutes, and JWKS lookups are themselves rate-limited (10 requests per minute) to protect the provider.
* **Expiry:** expired tokens are rejected; expiration is always enforced.

Obtain tokens from your OIDC provider (for example, a Keycloak realm). The service does not mint tokens and exposes no token-signing or debug-key endpoints.

## Authorization

Holding a valid token is not always sufficient — some routes additionally require a role. The service reads roles from the token's `realm_access.roles` array (client roles in `resource_access` are also honored).

* The **`admin`** role is required on the agent/DID, issuer-registration, verifier-registration, and holder/wallet management routes (`/agent/*` and `/holders/:holderId/*`).
* The remaining issuer routes (schemas, credential offers, issuance sessions, direct signing) and verifier routes (authorization requests, verification sessions, `/credentials/verify`) require a valid token but no specific role.
* Public routes — the root and version endpoints, and the hosted `did:web` documents — require no token at all.

A request with a valid token but an insufficient role is rejected with `403 Forbidden`.

### Development bypass

For local development, set `AUTH_DISABLED=true`. Every request is then treated as an authenticated `admin` principal and no token is required. **Never enable this outside local development.**

## Multi-Tenant Isolation

Each cloud-wallet **holder** is a per-user tenant created via `POST /agent/holder` and owned by the OIDC user (identified by the token's `sub`) who created it.

* An ownership guard enforces that a caller can only read or operate holders they own. Accessing another user's holder — listing its credentials, decoding them, or processing an offer/presentation URI through it — returns `403 Forbidden`.
* `GET /agent/holders` returns only the holders owned by the authenticated user.

This means the wallet tenant boundary is the `holderId` together with its owning user, not the raw token subject alone.

## Transport & Keys

* Always run the service behind **HTTPS** in production. OpenID4VCI and OpenID4VP flows require HTTPS, and insecure HTTP URLs are rejected by default.
* `ALLOW_INSECURE_HTTP=true` relaxes this for local development only. Do not set it in production.
* Protect your `.env` files, database credentials, and the OIDC provider configuration.
* Prefer short token TTLs, especially for automated/machine clients, and rotate provider keys periodically.
* The service does not implement credential revocation or status lists, so a verified credential is not checked against any revocation source — design your trust model around credential expiry and re-issuance instead.

## Rate Limiting

A global limit of **60 requests per 60 seconds** applies to the API. Serving of hosted `did:web` documents is exempt so that DID resolution by external parties is never throttled.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.empe.io/develop/wallet-server/security-considerations.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
