Skip to content

API Authentication

EUDIPLO uses OAuth 2.0 Client Credentials flow for API authentication, designed for service-to-service communication without user interaction.

Configuration

Key Type Notes
OIDC string Enable OIDC mode
OIDC_INTERNAL_ISSUER_URL string Internal issuer URL in OIDC mode [when OIDC is set → then default=undefined]
OIDC_CLIENT_ID any Client ID for OIDC [when OIDC is set → then required]
OIDC_CLIENT_SECRET any Client secret for OIDC [when OIDC is set → then required]
OIDC_SUB any Claim to use as subject [when OIDC is set → then default="tenant_id"]
OIDC_ALGORITHM any Expected JWT alg [when OIDC is set → then default="RS256"]
MASTER_SECRET any Master secret for JWT signing and encryption key derivation - required, minimum 32 characters [when OIDC is set → otherwise required]
JWT_ISSUER any Local JWT issuer [when OIDC is set → otherwise default="eudiplo-service"]
JWT_EXPIRES_IN any Local JWT expiration [when OIDC is set → otherwise default="24h"]
AUTH_CLIENT_SECRET any Client secret (local auth) - required when OIDC is not enabled [when OIDC is set → otherwise required]
AUTH_CLIENT_ID any Client ID (local auth) - required when OIDC is not enabled [when OIDC is set → otherwise required]

Authentication Architecture

Design Principles

  • Service-to-Service: No user interaction required
  • Tenant Isolation: JWTs are used to isolate tenant data
  • Pluggable Identity: Support for both built-in and external OIDC providers
  • Stateless: JWT tokens enable horizontal scaling

Security Model

  • All management endpoints require authentication
  • Tenant data is isolated using JWT subject claims
  • Tokens are signed and validated for integrity
  • Support for token expiration and rotation
  • Endpoints are role based protected

Related Architecture: For multi-tenant configuration and session management, see Tenant-Based Architecture and Sessions.

Import

Clients can be imported via configuration files. See Configuration Import for details.


OAuth2 Client Credentials Authentication

This API exclusively uses the OAuth2 client credentials flow, which is designed for service-to-service authentication where no user interaction is required.

EUDIPLO includes a built-in OAuth2 server for simple deployments:

  1. Swagger UI Authentication:

    • Navigate to the Swagger UI at /api
    • Click the "Authorize" button
    • Select "oauth2"
    • Enter client ID and secret (configured via environment variables)
    • Click "Authorize"
  2. Programmatic Access:

    Option 1: Credentials in Authorization Header (OAuth2 Standard):

    curl -X POST http://localhost:3000/oauth2/token \
      -H "Content-Type: application/json" \
      -H "Authorization: Basic $(echo -n 'client_id:client_secret' | base64)" \
      -d '{
        "grant_type": "client_credentials"
      }'
    

    Option 2: Credentials in Request Body:

    curl -X POST http://localhost:3000/oauth2/token \
      -H "Content-Type: application/json" \
      -d '{
        "grant_type": "client_credentials",
        "client_id": "your-client-id",
        "client_secret": "your-client-secret"
      }'
    

External OIDC Provider

For enterprise deployments with existing identity infrastructure, EUDIPLO can integrate with external OIDC providers like Keycloak, Auth0, or Azure AD.

Configuration:

OIDC=https://your-keycloak.example.com/realms/your-realm
PUBLIC_URL=https://your-api.example.com

Authentication Flow:

  1. Use your OIDC provider's token endpoint with client credentials flow
  2. Include the access token in API requests: Authorization: Bearer <token>

Configuration

External OIDC Provider

# Enable external OIDC
OIDC=true
OIDC_INTERNAL_ISSUER_URL=https://your-keycloak.example.com/realms/your-realm
PUBLIC_URL=https://your-api.example.com

Integrated OAuth2 Server

# Leave OIDC undefined for integrated OAuth2 server
# All three values below are REQUIRED
PUBLIC_URL=https://your-api.example.com
MASTER_SECRET=your-secret-key-here-minimum-32-characters
AUTH_CLIENT_ID=your-client-id
AUTH_CLIENT_SECRET=your-client-secret

Security: Secrets are hashed

Client secrets are securely hashed (bcrypt) before storage. They cannot be retrieved after creation. Use the Rotate Secret API endpoint or Web Client button to generate a new secret if needed.

Configuration Reference: For complete configuration options and environment variables, see Key Management and Database Configuration.

Protected Endpoints

All administrative endpoints require OAuth2 authentication and are protected by a role based access control approach.

The following roles are available:

/**
 * Enumeration of all roles available in the system.
 */
export enum Role {
    //to manage presentation resources
    Presentations = "presentation:manage",
    // to create offers
    PresentationRequest = "presentation:request",
    // to manage issuance resources
    Issuances = "issuance:manage",
    // to create offers
    IssuanceOffer = "issuance:offer",
    // to manage client resources
    Clients = "clients:manage",
    // to manage tenant resources
    Tenants = "tenants:manage",
    // to manage registrar configuration and operations
    Registrar = "registrar:manage",
}

/**
 * List of all roles
 */
export const allRoles = [
    Role.Tenants,
    Role.IssuanceOffer,
    Role.Issuances,
    Role.PresentationRequest,
    Role.Presentations,
    Role.Clients,
    Role.Registrar,
];

Each client can have multiple roles assigned, but each client can only be assigned to one tenant at maximum. The client with the tenant manage must not be assigned to any tenant since it is managing the service in general. There could be other roles in the future like limited access to the metrics endpoint.

Resource-Level Access Control

In addition to role-based access control, clients can be restricted to specific presentation or issuance configurations. This allows for fine-grained control over which configurations a service account can use.

Configuration Fields:

  • allowedPresentationConfigs: Array of presentation config IDs. If empty or null, the client can use any presentation config.
  • allowedIssuanceConfigs: Array of issuance config IDs. If empty or null, the client can use any issuance config.

Example: Creating a Restricted Client

curl -X POST http://localhost:3000/clients \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "partner-service",
    "roles": ["presentation:request", "issuance:offer"],
    "allowedPresentationConfigs": ["age-verification", "identity-check"],
    "allowedIssuanceConfigs": ["partner-credential"]
  }'

This client can only:

  • Create presentation requests for age-verification and identity-check configs
  • Create issuance offers for partner-credential config

If the client attempts to use a config not in their allowed list, a 403 Forbidden error is returned.

Use Cases:

  • Partner Integrations: Limit external partners to specific credential types
  • Department Isolation: Different departments use different credential configurations
  • Compliance: Ensure services only access configurations they are authorized to use

Note: These restrictions work with both the built-in OAuth2 server and external OIDC providers (e.g., Keycloak). When using an external OIDC provider, the restrictions are stored in EUDIPLO's database and applied during request validation.

Troubleshooting

Token Validation Errors

  1. Verify that tokens include the correct audience (eudiplo-service)
  2. Ensure clock synchronization between client and server
  3. Check token expiration times

Integrated OAuth2 Server Issues

  1. Verify MASTER_SECRET is at least 32 characters
  2. Ensure client credentials (AUTH_CLIENT_ID/AUTH_CLIENT_SECRET) are configured correctly
  3. Check that PUBLIC_URL is accessible for OAuth2 flows

Security Considerations

  • Token Lifetime: Tokens expire after 24 hours for client credentials flow. It can be updated by setting the JWT_EXPIRES_IN to another value, default value is 24h.
  • Secure Storage: Store client credentials and tokens securely and never expose them in logs or URLs
  • Service-to-Service: This API is designed for service-to-service authentication without user interaction