Java / Spring quickstart
Java 17+, Spring Boot 3.x.
implementation 'com.latchvector:latchvector-sso-spring-boot-starter:1.0.0'
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).
The starter README has the full recipes (multitenancy with JPA/Hibernate, go-live checks). Exact request/response shapes: API reference.