Camel Spring Boot

OpenFGA

Authorize an Exchange against an OpenFGA relationship graph, and maintain the relationship tuples it is authorized against.

What’s inside

Please refer to the above links for usage and configuration details.

Maven coordinates

<dependency>
    <groupId>org.apache.camel.springboot</groupId>
    <artifactId>camel-openfga-starter</artifactId>
</dependency>

Spring Boot Auto-Configuration

The starter supports 32 options, which are listed below.

Name Description Default Type

camel.component.openfga.api-audience

The audience to request the access token for in the client-credentials flow.

String

camel.component.openfga.api-token

Pre-shared token sent to OpenFGA in the Authorization header, for a server started with \{code --authn-method preshared}.

String

camel.component.openfga.api-token-issuer

The token endpoint the client-credentials flow exchanges its credentials at.

String

camel.component.openfga.api-url

The base URL of the OpenFGA HTTP API, without a trailing path. The default assumes OpenFGA running as a sidecar on its standard HTTP port.

http://localhost:8080

String

camel.component.openfga.authorization-model-id

The identifier of the authorization model revision to evaluate against. Leave it empty to use whichever model the store considers latest. Pin it in production. A store keeps every model it was ever given and latest moves the moment somebody writes a new one, so an unpinned endpoint can start answering a different question than the one it was reviewed with - without any change to the route. Pinning also makes a model rollout a deliberate, reviewable configuration change.

String

camel.component.openfga.autowired-enabled

Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc.

true

Boolean

camel.component.openfga.client-id

Client identifier for the OAuth 2.0 client-credentials flow, for a server that authenticates through an OIDC provider. Setting it selects that flow, so clientSecret, apiTokenIssuer and apiAudience are then required too.

String

camel.component.openfga.client-secret

Client secret for the OAuth 2.0 client-credentials flow.

String

camel.component.openfga.condition-context

Context passed to the CEL expressions of any conditioned relation the check touches, as a map resolved from the registry - conditionContext=#myContext. A map rather than an expression on purpose: OpenFGA types every condition parameter in the authorization model (int, bool, timestamp, ipaddress), and a map lets the route author supply values of the right Java type instead of strings that the server would then reject. A mistyped value is refused with an HTTP 400, which this component treats as a denial rather than as an unavailable decision point, so the failure direction is safe either way. Like contextualTuples this is endpoint-only. A condition can decide a relation, so letting a message choose the values it is evaluated with would hand the caller the decision.

Object>

camel.component.openfga.configuration

The component configuration. The option is a org.apache.camel.component.openfga.OpenFgaConfiguration type.

OpenFgaConfiguration

camel.component.openfga.connect-timeout

How long to wait for the connection to OpenFGA to be established. The component applies this itself rather than through the SDK’s own connectTimeout setting, which as of openfga-sdk 0.10.1 is accepted and then never read, leaving the connect phase bounded only by the operating system. The option is a long type.

10000

Long

camel.component.openfga.consistency

The consistency the query is answered with. OpenFGA’s default, MINIMIZE_LATENCY, may answer from a replica that has not caught up yet, which right after a revoke means a tuple that was deleted can still grant access for a moment. Set HIGHER_CONSISTENCY on the paths where that window matters, at the cost of latency. Left unset, OpenFGA’s own default applies.

String

camel.component.openfga.contextual-tuples

Relationship tuples supplied for the duration of one check and never stored, as semicolon-separated user,relation,object triples - for example user:$\{exchangeProperty.authenticatedSubject},member,team:eng. Each part is evaluated as a Simple expression against the exchange, exactly as user and object are, and applies to check, batchCheck, listObjects, listRelations and listUsers. This is how a route hands OpenFGA a relationship the stored graph does not hold - a group membership that lives in the token rather than in the store, or a fact about the request such as which network it arrived on. A contextual tuple grants. It is read exactly like a stored tuple, so user:anne,owner,document:secret makes \{code check(user:anne, owner, document:secret)} answer true whatever the store contains. That is why this option is endpoint-only and is never taken from the message: a tuple the caller could choose would let it assert the very relationship being checked. By the same token, an expression here that reads an inbound header hands the caller that power anyway - keep these literal, or derive them from something the route established rather than from what it received. A part that resolves to blank denies the exchange rather than being dropped: the route asked for a tuple it did not get, and continuing without it would answer a different question than the one configured.

String

camel.component.openfga.enabled

Whether to enable auto configuration of the openfga component. This is enabled by default.

Boolean

camel.component.openfga.fail-open

Whether to let the exchange proceed when OpenFGA could not be asked at all, for example because the server is unreachable. Disabled by default so that an unavailable decision point denies rather than grants access. Do not enable this in production. It applies to the check operation and to OpenFgaSecurityPolicy, the two places where proceed has a meaning, and it covers only a failure to obtain a verdict. An exchange that was denied, and an exchange that carried no usable subject or object, are decisions rather than failures and are never turned into an allow by this flag. The other operations ignore it. A batchCheck or listObjects that failed has no safe way to proceed - returning the objects it never managed to filter would be the leak the filtering was there to prevent - so a failure there is reported as an error for the route’s own error handling to deal with.

false

Boolean

camel.component.openfga.health-check-consumer-enabled

Used for enabling or disabling all consumer based health checks from this component

true

Boolean

camel.component.openfga.health-check-producer-enabled

Used for enabling or disabling all producer based health checks from this component. Notice: Camel has by default disabled all producer based health-checks. You can turn on producer checks globally by setting camel.health.producersEnabled=true.

true

Boolean

camel.component.openfga.lazy-start-producer

Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing.

false

Boolean

camel.component.openfga.max-parallel-requests

How many of a batchCheck’s checks may be in flight at once. The batch is issued as one request per object, so this bounds the load one exchange puts on the server.

10

Integer

camel.component.openfga.max-retries

How many times the SDK retries a request that failed in a way worth retrying, such as a rate limit or a 5xx. Set it to 0 to disable retries; the overall wait a routing thread can spend on one exchange grows with it.

3

Integer

camel.component.openfga.object

The object being accessed, as an OpenFGA object identifier such as \{code document:budget}. Evaluated as a Simple expression against each exchange, so document:$\{header.documentId} names the resource the message is about. Unlike the subject, taking the object from a header is normal and safe: the caller is entitled to say which resource it wants, and the check is what decides whether it may have it.

String

camel.component.openfga.open-fga-client

An existing OpenFgaClient to use. When set, every option describing how to reach the server - apiUrl, storeId, the credentials, the timeouts and sslContextParameters - is ignored, because they are baked into the client that was handed over. The option is a dev.openfga.sdk.api.client.OpenFgaClient type.

OpenFgaClient

camel.component.openfga.read-timeout

How long to wait for one request to OpenFGA to complete once connected. A request that times out is a failure to obtain a verdict rather than a deny, so it fails closed - or proceeds when failOpen is set. The option is a long type.

10000

Long

camel.component.openfga.relation

The relation to demand, such as reader or owner. Evaluated as a Simple expression against each exchange, though a literal is what you usually want. The relation is the permission being demanded, so resolving it from an inbound header lets the caller pick the weakest one the model defines. Keep it literal, or derive it from something the route controls such as $\{header.CamelHttpMethod}.

String

camel.component.openfga.relations

Comma-separated list of relations the listRelations operation asks about, for example reader,writer,owner. Only the ones the subject actually holds come back.

String

camel.component.openfga.scopes

Space-separated scopes to request in the client-credentials flow.

String

camel.component.openfga.ssl-context-parameters

TLS configuration for the connection to OpenFGA. Needed to trust a server whose certificate comes from a private CA, and to present a client certificate to a server that requires mutual TLS - a SPIFFE X.509-SVID obtained with \{code camel-spiffe}, for instance, so the workload authenticates to the decision point as itself. The option is a org.apache.camel.support.jsse.SSLContextParameters type.

SSLContextParameters

camel.component.openfga.store-id

The identifier of the OpenFGA store holding the relationship tuples and the authorization model, as returned by \{code fga store create}. The store is the relationship graph that judges the exchange, so it comes from the endpoint only and is never taken from a message header.

String

camel.component.openfga.type

The object type to enumerate for the listObjects operation, for example document. This is a type name from the authorization model, so it is taken literally rather than evaluated.

String

camel.component.openfga.use-global-ssl-context-parameters

Enable usage of global SSL context parameters.

false

Boolean

camel.component.openfga.user

The subject to authorize, as an OpenFGA user identifier such as \{code user:anne}. Evaluated as a Simple expression against each exchange, so a literal is used as-is and user:$\{exchangeProperty.CamelKeycloakTokenSubject} resolves whatever an earlier step established. Read it from an exchange property rather than a header wherever you can. An exchange property is set by the route itself - by the step that verified the caller - and nothing outside the route can set one. A header, by contrast, is often whatever the caller sent, and an endpoint configured as user:$\{header.userId} lets the caller choose who to be. \{code camel-keycloak}'s KeycloakSecurityPolicy already follows that reasoning: it reads the subject from the CamelKeycloakTokenSubject exchange property in preference to the header of the same name, its preferPropertyOverHeader option defaulting to true. Nothing in Camel sets the property for you, so the step that validates the token has to record it - but recording it under that name lets one identity serve both. An expression that resolves to blank, or to a bare \{code user:} prefix, denies the exchange: an exchange carrying no identity is not authorized, and failOpen does not apply to it.

String

camel.component.openfga.user-filters

Comma-separated list of user filters for the listUsers operation, naming which kinds of subject to return. An entry is either a type, user, or a type and a relation, team#member, to return the usersets holding the relation rather than the individual subjects. Defaults to user.

String