> 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/issuer/security-considerations.md).

# Security Considerations

The sections below describe how the Issuer Service protects its API, the credentials it issues, and the signing keys it manages.

1. **API Authentication and Authorization**:
   * **OIDC JWT Bearer tokens**: Every non-public endpoint requires an OIDC-issued JWT presented as `Authorization: Bearer <token>`. Tokens are validated against the JWKS endpoint configured in `OIDC_JWKS_URL`: the signature is verified with `RS256`, the signing key is selected by matching the token's `kid` against the JWKS, and expiration is enforced. Fetched signing keys are cached for roughly 10 minutes (with a request limit of 10 JWKS fetches per minute) to limit round-trips to the identity provider. A request with a missing, malformed, or expired token is rejected with `401 Unauthorized`.
   * **Role-based access**: The `admin` role is additionally enforced on agent management routes (`/agent/*` — DID, issuer, verifier and holder management) and on cloud-wallet routes (`/holders/:holderId/*`). For these routes, the service inspects the token's realm roles (`realm_access.roles`) and client roles (`resource_access`) and rejects any caller without the `admin` role with `403 Forbidden`. Cloud-wallet routes additionally enforce ownership, so a caller can only access the holders they created. The remaining Issuer endpoints (schema management, credential offers, issuance sessions and direct signing) and the Verifier endpoints require only a valid token — they carry no role requirement. Restrict who can obtain tokens carrying the `admin` role in your identity provider.
   * **Development bypass**: Setting `AUTH_DISABLED=true` disables token validation and treats every request as an authenticated `admin` user. This is a local-development convenience only and must never be enabled in production.
2. **Public Endpoints**: A number of endpoints are intentionally unauthenticated: `GET /` (hello), `GET /version`, and the hosted DID document routes (`GET /:uuid/did.json` and `GET /:uuid/.well-known/did.json`). These expose only public information — a service identifier, a version string, and DID documents that are meant to be world-readable so that verifiers can resolve issuer keys. Also public are the Swagger docs (`GET /api-docs`, `GET /api-docs-json`) and the wallet-facing OpenID4VCI/OpenID4VP protocol endpoints mounted under the `ISSUER_BASE_URL`/`VERIFIER_BASE_URL` paths (credential-issuer metadata, token, credential, and authorization-request/response endpoints), which are public by protocol design.
3. **Transport Security**: Always use HTTPS to protect tokens and credentials in transit. The OpenID4VCI issuance flow requires HTTPS in production. The `ALLOW_INSECURE_HTTP=true` flag permits plain HTTP for local development only and must be left unset (or `false`) in any deployed environment.
4. **Credential Integrity**: Issued credentials are cryptographically signed with the issuer's `Ed25519` key using the `EdDSA` algorithm. The signature binds the claims to the issuing DID, so any tampering with a credential — for example with an `EmployeeBadge@1.0:sd-jwt` credential — invalidates the signature and causes verification to fail. For SD-JWT VC credentials, selective disclosure lets a holder reveal only chosen claims while the issuer signature still covers the full set.
5. **Rate Limiting**: A global throttle of 60 requests per 60 seconds is applied to guard against brute-force and abuse. DID document serving is exempt so that verifiers can always resolve issuer keys. Requests exceeding the limit receive `429 Too Many Requests`.
6. **Access Controls and Monitoring**: In addition to the built-in token validation and role-based access control, operators should apply standard hardening at the network layer: IP allow-listing, firewalls, and audit logging to track sensitive operations and surface suspicious activity.
7. **Key Management**: Issuer signing keys are `Ed25519` keys held in an internal, database-backed key-management system; private key material is never exposed through the API. Automated key rotation is not available today; it is a planned future capability (see [Future Enhancements](/develop/issuer/future-enhancements.md)).


---

# 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/issuer/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.
