Skip to main content

Java / Spring quickstart

Java 17+, Spring Boot 3.x.

implementation 'com.latchvector:latchvector-sso-spring-boot-starter:1.0.0'
The SDK is the whole product — you rarely touch raw HTTP

The starter wraps every endpoint: authentication, and the full management surface (users, organizations, roles, applications, API clients, webhooks, audit, bulk import, data export/erase, MFA & devices). Reach for the API reference only to look up an exact request/response shape.

1. Protect an API — two properties​

The Spring Boot starter is the framework integration: add the dependency, set two properties, and it auto-configures the security layer.

latchvector:
sso:
issuer: https://sso.yourdomain.com
audience: https://api.yourcompany.com # your registered identifier

The starter builds a JwtDecoder wired to the right validators, so an ordinary resource-server config works:

@Bean
SecurityFilterChain api(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.oauth2ResourceServer(oauth -> oauth.jwt(Customizer.withDefaults()))
.build();
}

Controllers take a Principal directly, and method security (@PreAuthorize) sees the token's permissions as authorities.

2. Log a user in​

SsoClient sso = new SsoClient(issuer, audience, 2, RestClient.create());
Object result = sso.login(email, password);
if (result instanceof TokenPair tokens) {
String access = tokens.accessToken();
String refresh = tokens.refreshToken();
}

3. Manage everything — one client​

ManagementClient wraps the entire management surface, one method per endpoint, so the whole product is reachable from code — you rarely write a raw request.

ManagementClient mgmt = new ManagementClient(issuer, tokens::accessToken, 2, RestClient.create());

mgmt.createUser(Map.of("organizationId", orgId, "email", email, "fullName", name));
mgmt.createOrganization(Map.of("name", name, "slug", slug, "parentId", parentId));
mgmt.createRole(Map.of("organizationId", orgId, "name", "Doctor",
"scope", "SUBTREE", "permissionCodes", List.of("USER_MANAGE")));
mgmt.createApplication(Map.of("organizationId", orgId, "identifier", identifier, "name", name));
mgmt.registerClient(Map.of("organizationId", orgId, "name", name, "scopes", List.of("reports.read")));
mgmt.registerWebhook(Map.of("organizationId", orgId, "applicationId", appId, "url", url));
mgmt.searchAudit(Map.of("organizationId", orgId, "q", "role.revoked"));
mgmt.importValidate(payload); // bulk migrate
mgmt.eraseUser(userId); // export / erase
mgmt.mfaSetupBegin(); // the caller's own MFA
mgmt.listMyDevices(); // the caller's devices
mgmt.provisionSandbox(Map.of(/* … */)); // platform operators

Anything not covered by a method — including endpoints added after this SDK shipped — is reachable via mgmt.request(HttpMethod, path, query, body).

Deeper reference

The starter README has the full recipes (multitenancy with JPA/Hibernate, go-live checks). Exact request/response shapes: API reference.