Skip to content

Java SDK

com.axowl:axowl-sdk is the backend SDK for JVM services: it verifies the access token an end user presents to your API and tells you who they are and what they may do. It mirrors @axowl/sdk-backend (Node) and Axowl.Sdk.Identity.Client (.NET). Java 17+, one dependency (com.nimbusds:nimbus-jose-jwt).

<dependency>
<groupId>com.axowl</groupId>
<artifactId>axowl-sdk</artifactId>
<version>0.1.0</version>
</dependency>
import com.axowl.sdk.*;
AxowlConfig config = AxowlConfig.builder("my-org") // your Axowl organization
.audience("app_my_main") // optional: your application key
.build(); // baseUrl defaults to https://api.axowl.com
AxowlTokenVerifier verifier = new AxowlTokenVerifier(config); // one per config — keep it as a singleton
try {
AxowlContext ctx = verifier.verify(bearerToken);
ctx.userId(); ctx.email(); ctx.orgSlug(); ctx.connectedId(); ctx.isEmployee();
ctx.permissions(); // ["wallet.read", "report.*"]
ctx.can("report.monthly"); // true — wildcards honoured
Permissions.require(ctx, "wallet.withdraw"); // throws AxowlPermissionException
} catch (AxowlAuthException e) {
e.reason(); // missing_token | invalid_token | expired | signature | issuer | audience | jwks
}

What is checked, and against what:

CheckSource
Signature (RS256){baseUrl}/api/public/orgs/{orgSlug}/.well-known/jwks.json — cached 10 min, re-fetched (rate-limited) on an unknown kid
issmust equal {baseUrl}/api/public/orgs/{orgSlug} — what Axowl writes into every end-user token
audonly when audience is configured; then it must equal your application key
exp / nbfenforced; leewaySeconds on the builder absorbs clock drift

AxowlContext is a record with every claim (claims()) plus typed accessors: userId (sub), email, orgId, orgSlug, appKey, appGroupId, connectedId (the user’s org badge), type ("enduser"), isEmployee, and permissions — the token stores permissions as a JSON string; the SDK hands you a list.

@Bean
FilterRegistrationBean<AxowlAuthFilter> axowlAuth(AxowlTokenVerifier verifier) {
var reg = new FilterRegistrationBean<>(new AxowlAuthFilter(verifier));
reg.addUrlPatterns("/api/*");
return reg;
}
@GetMapping("/api/wallet")
Map<String, Object> wallet(HttpServletRequest request) {
AxowlContext ctx = AxowlAuthFilter.context(request);
Permissions.require(ctx, "wallet.read");
return Map.of("user", ctx.email());
}

AxowlAuthFilter needs jakarta.servlet-api on your classpath (declared provided). A missing or invalid token answers 401 {"error": …, "reason": …} — the same shape as the Express middleware. Map AxowlPermissionException to 403 {"error": …, "required": [...]} in your exception handler.

The JWT fast path cannot see a permission revoked after the token was issued. For decisions that must, ask Axowl with your org API key (ah_live_…, from Organization → API keys):

AxowlIdentityClient identity = new AxowlIdentityClient("ah_live_...", "https://api.axowl.com");
var res = identity.introspect(bearerToken); // active, principal, expiresAt, issuedAt
var chk = identity.checkPermission(bearerToken, "wallet.withdraw"); // granted, matchedScopes, reason

These call POST /v1/identity/introspect and POST /v1/identity/check-permission — the REST form of the gRPC IdentityService described on the Identity SDK page. Pass your own java.net.http.HttpClient and timeout through the four-argument constructor.

Identical to every other Axowl SDK and to the server:

PatternScopeMatch
sap.fi.document.postsap.fi.document.postyes
sap.fi.*sap.fi.document.postyes
*anythingyes
sap.fisap.fi.document.postno — a prefix without * is not a wildcard

Permissions.hasPermission, hasAllPermissions, hasAnyPermission, matchScope and require are static and usable outside a request.