Documentation
/
SDK Reference
/
Backend
/
Java
/
Java SDK API Reference

Java SDK API Reference

Complete API reference for the Hawcx Java SDK

Java SDK API Reference

All public types live under com.hawcx. Add the dependency:

<dependency>
    <groupId>com.hawcx</groupId>
    <artifactId>hawcx-java-sdk</artifactId>
    <version>0.2.0</version>
</dependency>

HawcxOauthClient

The OAuth client. Thread-safe; construct once and reuse.

import com.hawcx.oauth.HawcxOauthClient;
import com.hawcx.oauth.HawcxOauthConfig;

HawcxOauthConfig config = new HawcxOauthConfig(System.getenv("HAWCX_BASE_URL"));
HawcxOauthClient client = new HawcxOauthClient(config);

HawcxOauthConfig exposes two endpoint helpers:

  • config.tokenEndpoint()<baseUrl>/oauth2/token
  • config.keysEndpoint()<baseUrl>/keys (use this as the jwksUrl for JwtVerifier.VerifyOptions)

exchangeCode(TokenRequest)

Exchange an authorization code for an id_token without verifying it. Useful when you only need the raw token. Most apps should use exchangeCodeForClaims instead.

TokenRequest req = new TokenRequest(configId, authCode, codeVerifier);
TokenResponse resp = client.exchangeCode(req);
String idToken   = resp.getIdToken();
String tokenType = resp.getTokenType();
long   expiresIn = resp.getExpiresIn();

exchangeCodeForClaims(TokenRequest, VerifyOptions)

Exchange the code, verify the returned id_token, and return the claims. The recommended end-to-end entry point.

JsonObject claims = client.exchangeCodeForClaims(req, opts);
String userId = claims.get("sub").getAsString();

exchangeCodeForTokenAndClaims(TokenRequest, VerifyOptions)

Same as above but also returns the raw TokenResponse, useful when you need the id_token itself (e.g. to set as a cookie):

HawcxOauthClient.TokenAndClaims result = client.exchangeCodeForTokenAndClaims(req, opts);
String     idToken = result.tokenResponse().getIdToken();
JsonObject claims  = result.claims();

verifyJwt(String token, VerifyOptions)

Standalone JWT verification, useful when you already have a token (e.g. from a session cookie) and just want to validate it.

JsonObject claims = client.verifyJwt(idToken, opts);

getKeys(TokenRequest)

Fetch the raw JWKS document for inspection. Most callers don't need this; JwtVerifier fetches and caches JWKS internally via jwksUrl.

KeysResponse keys = client.getKeys(req);
JsonObject jwks   = keys.getJwks();

TokenRequest

Value object describing a single token exchange.

// Without redirect URI:
new TokenRequest(configId, authCode, codeVerifier);

// With OAuth 2.0 redirect URI (required by some providers):
new TokenRequest(configId, authCode, codeVerifier,
                 "https://app.example.com/auth/callback");

JwtVerifier.VerifyOptions

Builder-style options controlling JWT verification. Build one per audience/issuer pair and reuse.

import com.hawcx.oauth.JwtVerifier;

JwtVerifier.VerifyOptions opts = JwtVerifier.VerifyOptions.builder()
    .jwksUrl(config.keysEndpoint())     // OR .publicKeyPem("-----BEGIN PUBLIC KEY-----...")
    .audience(System.getenv("HAWCX_CONFIG_ID"))
    .issuer(System.getenv("HAWCX_BASE_URL"))
    .verifyExp(true)                    // default true
    .leewaySeconds(10)                  // default 0; tolerate small clock skew
    .algorithms(java.util.Set.of(JWSAlgorithm.RS256))   // default: RS256, ES256/384/512, EdDSA
    .build();
MethodDefaultNotes
jwksUrl(String)(none)Either this or publicKeyPem must be set. JWKS is fetched once per TTL window (default 1h) and cached.
publicKeyPem(String)(none)Static PEM key. Use for fixed-key setups or tests.
audience(String)not validatedExpected aud claim. Set this in production.
issuer(String)not validatedExpected iss claim. Set this in production.
verifyExp(boolean)trueDisable only for unit tests.
leewaySeconds(long)0Tolerated clock skew, in seconds.
algorithms(Set<JWSAlgorithm>)RS256, ES256, ES384, ES512, EdDSAOnly tokens signed with one of these algorithms are accepted.

JwksCache

In-memory TTL cache for JWKS documents. Defaulted automatically by HawcxOauthClient. Override only if you need a custom TTL or want to share a cache across clients:

import com.hawcx.oauth.JwksCache;
import com.hawcx.oauth.JwtVerifier;

JwksCache cache = new JwksCache(/* ttlSeconds */ 600);
JwtVerifier verifier = new JwtVerifier(cache);
HawcxOauthClient client = new HawcxOauthClient(config, verifier);

Delegation Client

Optional: advanced flows only

The delegation client is only required for backend-driven MFA setup/verify, suggested-MFA policy, device management, and step-up authentication. Apps that only need OAuth code exchange can skip this section.

Backend-driven MFA setup, user management, and device management. Every request is automatically encrypted (ECIES X25519 + AES-GCM) and signed (Ed25519 / RSA-PSS). Construct once and reuse; thread-safe.

DelegationClient.fromSecretKey(baseUrl, secretKey, configId)

import com.hawcx.delegation.DelegationClient;

DelegationClient client = DelegationClient.fromSecretKey(
    System.getenv("HAWCX_BASE_URL"),
    System.getenv("HAWCX_SECRET_KEY"),    // hwx_sk_v1_...
    System.getenv("HAWCX_CONFIG_ID")
);

Or with a raw KeyMaterial bundle:

DelegationClient client = DelegationClient.fromKeys(
    baseUrl,
    KeyMaterial.builder()
        .spSigningKey(spEd25519PrivateKeyPem)
        .spEncryptionKey(spX25519PrivateKeyPem)
        .idpVerifyKey(idpEd25519PublicKeyPem)
        .idpEncryptionKey(idpX25519PublicKeyPem)
        .build(),
    configId
);

MFA

import com.google.gson.JsonObject;
import com.hawcx.delegation.MfaMethod;

// Initiate (Email / SMS / TOTP)
JsonObject init = client.mfa.initiate(
    "[email protected]",
    MfaMethod.SMS,
    "+15551234567",   // null for EMAIL/TOTP
    null              // optional target method when changing
);
String sessionId = init.get("session_id").getAsString();

// Verify the OTP and complete the change
client.mfa.verify("[email protected]", sessionId, "123456");

Users

JsonObject creds = client.users.getCredentials("[email protected]");

// Suggested-MFA preference: "none", "always", or "risk_only"
client.users.setSuggestedMfa("[email protected]", "always");
JsonObject pref = client.users.getSuggestedMfa("[email protected]");

Devices

JsonObject devices = client.devices.list("[email protected]");

client.devices.revoke("[email protected]",   "device-h2index");
client.devices.unrevoke("[email protected]", "device-h2index");
client.devices.delete("[email protected]",   "device-h2index");

Generic request

For endpoints not covered by a typed namespace method:

JsonObject body = new JsonObject();
body.addProperty("userid", "[email protected]");
JsonObject response = client.request("/v1/management/users/phone", body);

Exception Hierarchy

Every SDK error extends com.hawcx.HawcxException (which extends RuntimeException). Catch the root if you only want one handler:

HawcxException
├── HawcxOauthException             : token exchange failures (network, 4xx/5xx, missing id_token)
├── JwtVerificationException        : signature / claims validation failures
├── InvalidPublicKeyException       : JWKS unreachable, no usable keys, malformed PEM
└── DelegationException             : base for delegation errors
    ├── DelegationCryptoException   : ECIES / signature operation failures
    ├── DelegationRequestException  : HTTP failure; carries statusCode + responseBody
    └── DelegationResponseException : response signature, timestamp, or decryption checks failed
try {
    JsonObject claims = client.exchangeCodeForClaims(req, opts);
} catch (HawcxException e) {
    log.error("Hawcx SDK call failed", e);
}