Px/

Java SDK — Overview

authorization-core is a Java SDK that adds declarative @Resource-based access control to Spring Boot and Quarkus services via AOP and CDI interception.

Edit this page on GitHub

authorization-core (io.gitlab.ctu-iotlab:com.authorization.core) is a Java 17 library that integrates Permix into your JVM microservices. It provides:

  • A @Resource annotation you place on any method or class
  • An interceptor (Spring AOP / Quarkus CDI) that calls Permix before every annotated invocation
  • A startup initializer that auto-registers all discovered resources on boot
  • Framework auto-configuration for Spring Boot and Quarkus — zero boilerplate

Maven dependency#

xml
<dependency>
  <groupId>io.gitlab.ctu-iotlab</groupId>
  <artifactId>com.authorization.core</artifactId>
  <version>0.1.5</version>
</dependency>

Published to Maven Central under the MIT License. Requires Java 17+.


The @Resource annotation#

java
@Inherited
@InterceptorBinding          // CDI binding
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Resource {
    String   name()         default "";  // unique key, e.g. "invoice:read"
    String   displayName()  default "";  // human-readable label
    String[] defaultRoles() default {};  // roles bootstrapped on first registration
}

@Resource can be placed on a method (recommended) or a class (applies to all methods). In Quarkus, the interceptor checks the method annotation first and falls back to the class annotation.


How it works at runtime#

Every time an annotated method is called, the interceptor:

  1. Reads all inbound HTTP request headers via HeaderExtractor.
  2. Strips restricted headers (connection, host, content-length, expect, upgrade, transfer-encoding) via HeaderSanitizer.
  3. Forwards the sanitized headers plus calls POST /resources/access/check with {"name": "<resource-name>"}.
  4. If the response is {"authorized": false} or the request fails → throws SecurityException → interceptor turns it into HTTP 403.
  5. If enabled = false in config → the check is skipped entirely (method proceeds normally).
rounded-md border px-1.5 py-0.5 font-mono text-[0.82em]
Inbound Request
      │
      ▼
HeaderExtractor ──► HeaderSanitizer ──► GenericRestClient
                                              │
                                   POST /resources/access/check
                                   {"name": "invoice:read"}
                                              │
                                   {"authorized": true/false}
                                              │
                              ┌───────────────┴───────────────┐
                           allowed                         denied
                              │                               │
                         proceed()                  SecurityException → 403

Startup resource registration#

On application startup, ResourceInitializer discovers every @Resource-annotated method in your codebase and registers them with Permix so that roles and policies can be managed centrally.

Registration flow:

  1. SpringInitialize/QuarkusInitialize runs @PostConstruct.
  2. ResourceCollectorAdapter.collect() scans all beans/CDI beans for @Resource methods.
  3. Calls TokenProvider.getAdminToken() → performs client_credentials token exchange against {AUTH_SERVER_URL}/protocol/openid-connect/token.
  4. Calls POST /resources/list with all discovered resources in one batch.

Self-skip guard

If ctu.iotlab.resource-config.service-name equals ctu-resource-management-service (the Permix itself), the initializer skips registration to prevent a bootstrap loop.

Registration payload sent per resource:

json
{
  "name":         "invoice:read",
  "displayName":  "Read Invoice",
  "serviceName":  "invoice-service",
  "defaultRoles": ["finance", "admin"]
}

Configuration reference#

All keys are read through ApplicationConfigProvider (Spring Environment or MicroProfile Config).

Property keyRequiredDescription
ctu.iotlab.resource-config.urlBase URL of Permix
ctu.iotlab.resource-config.service-nameLogical name of this microservice
ctu.iotlab.resource-config.enabledtrue to enable enforcement; any other value disables all checks
ctu.iotlab.resource-config.client-secretOAuth2 client secret (fallback if ADMIN_CLIENT_SECRET env var not set)
ctu.iotlab.resource-config.dev-modeNot read directly; dev mode is detected from the active Spring/Quarkus profile

Environment variables (read via System.getenv):

Env varDefaultDescription
ADMIN_CLIENT_IDiotlab-adminOAuth2 client ID for token exchange
ADMIN_CLIENT_SECRET(from client-secret property)OAuth2 client secret

Framework-specific OIDC URL keys (used by TokenProvider):

FrameworkProperty key
Quarkusquarkus.oidc.auth-server-url
Spring Bootspring.security.oauth2.resourceserver.jwt.issuer-uri

The token URL is constructed as {AUTH_SERVER_URL}/protocol/openid-connect/token.


Dev mode#

Dev mode is detected automatically from the active profile — no explicit property needed:

FrameworkDev mode condition
Spring BootActive profiles contain "dev" (spring.profiles.active=dev)
QuarkusActive profiles contain "dev" (quarkus dev sets this automatically)

In dev mode:

  • Startup registration is skipped — a log message is printed instead.
  • Runtime checks still run (enforcement is controlled by ctu.iotlab.resource-config.enabled, not the profile).

To also disable runtime checks in development, set ctu.iotlab.resource-config.enabled=false.


Logging#

The SDK uses System.out.println with a structured log format (no SLF4J/Log4j dependency required):

rounded-md border px-1.5 py-0.5 font-mono text-[0.82em]
2025-09-10 08:00:00,123 INFO [com.ctu.iotlab] (main) Resource sync process started. Activated profile dev.
2025-09-10 08:00:00,456 INFO [com.ctu.iotlab] (main) Scanned 12 resources.

On incomplete token config (missing tokenUrl, clientId, or clientSecret), a WARN line is printed listing the missing fields and registration is skipped gracefully.


Changelog#

VersionDateNotes
0.2.02025-10-15Removed hard Keycloak dependency; service API key auth for resource registration
0.1.52025-09-10Fixed wrong active-profile detection
0.1.42025-08-31Enhanced Spring exception handling; improved application.properties reading
0.1.02025-07-20Bulk resource registration via POST /resources/list
0.0.12025-06-01Initial release — @Resource annotation, single resource registration