UIAMUnified identity & access management
A unified identity control plane for people, service accounts and AI agents. Built on Kotlin, Spring Boot 4 and Spring Security 7 with an embedded OAuth2 authorization server: 16 data domains, 56 tables and 77 controllers covering everything from tenant isolation to tool-level authorization for agents, homogeneous across MySQL and PostgreSQL.
The identity kernel is not a login shell: tenant filtering is enforced by a jOOQ VisitListener in the query layer, agent delegation runs through RFC 8693 token exchange, and tool calls must pass tool-level authorization.
Consolidate the accounts, permissions and audit trails scattered across every business system into one governable identity kernel.
What problem does it actually solve
Four core capabilities, mapped to four real business needs.
Consolidates identity information and entitlement systems and breaks down user silos across platforms: SMS verification codes, social login, invitation-based sign-up and open-platform authorization, delivered as one user lifecycle service.
The identity core inside the enterprise: unified management of org structure, positions and permissions, internal SSO, and lifecycle automation from onboarding through transfer to offboarding.
One platform carries both internal employees and external users, with separate governance domains for each, a unified policy engine and a common security baseline.
Issues identities, credentials, scopes and call quotas to autonomously running AI agents; every action is traceable and can be revoked instantly.
Capabilities at a glance
- Embedded OAuth 2.1 / OIDC authorization server: authorization code, client credentials, refresh tokens and token exchange
- Strong multi-tenant and multi-space isolation, with tenant_id in the JWT as the single source of truth
- Fine-grained RBAC: functional and data permissions on two tracks, taking effect immediately
- WebAuthn / passkeys, magic links, TOTP MFA, device management, IP rules and sensitive-word policies
- Four Agent IAM pillars: machine principals → delegation chains → multi-hop propagation → MCP tool authorization
- Connector ecosystem: WeCom, WeChat Open Platform, mini programs, GitHub and Google out of the box
Not a product that lives in slides
The numbers below come from the real code in the uiam-coplit repository: modules, tables, endpoints and capability items.
Tech stack
Go deeper
Each subpage answers a specific kind of question — not the same content re-typeset.
Features
6 business domains, 43 concrete capabilities — each one backed by an implementation that exists in the code.
Multi-tenant & space isolation
uiam-core · 01-tenant · 02-spaceThe tenant boundary is the security boundary — filtering is enforced in the query layer, not left to someone remembering the WHERE clause.
- Tenant management: tenant CRUD, tenant configuration, tenant quotas, tenant settings and tenant discovery
- Space management: multiple spaces per tenant, space members, space security settings and public spaces
- The TenantScopedTables registry declares 45 tables as tenant-scoped in one central place
- TenantScopeVisitListener detects missing tenant predicates at the jOOQ query layer, switchable between DETECT_LOG and DETECT_THROW
- tenant_id in the JWT is the single source of truth; a mismatching header claim fails immediately with TenantMismatchException (403)
- The UserContext ThreadLocal is cleared on every request to prevent cross-request leakage
- runAsSystem / runWithoutTenantFilter are explicit bypass channels, and the bypass itself is audited
Authentication & credentials
uiam-authn · uiam-protocolFrom passwords to passkeys to passwordless — credentials of different strength coexist on one chain.
- Username and password login: password policy, password history, account lockout, password reset
- The full OAuth 2.1 grant set: authorization code, client credentials, refresh tokens, token revocation
- Standard OIDC endpoints: Discovery, JWKS, authorization, the consent page, token, introspection
- WebAuthn / passkey passwordless authentication, together with device management and device policies
- Magic-link email passwordless login, with verification codes and human verification
- TOTP MFA enrollment, verification and backup codes; the MFA enrollment flow can integrate external systems
- Application keys and JWT circulation for server-to-server calls
- Personal API keys and user-level API key management, with introspection-based validation
Authorization & permissions
uiam-authz · 07-authzRBAC as the base, data permissions alongside, token exchange for trimming.
- Role management and permission management, with role–permission and user–role associations
- Data permissions: the Sys data-permission service computes visible data by scope
- Tenant-level and space-level permissions in layers, plus user resource and user permission views
- Token Exchange (RFC 8693): both impersonation and delegation modes
- Delegation intersects application permissions ∩ user permissions, trimmed by the maxPermissionLevel cap
- The act claim expresses who acts for whom and supports multi-hop nested delegation chains
- Menus and application groups: app groups, user applications, application–space bindings
Agent identity & tool authorization
uiam-agent · 16-agentAI agents are first-class principals, not humans borrowing tokens to work in secret.
- MACHINE subject_type: service accounts and agents no longer masquerade as USER; tokens carry principal_type=machine
- Machine principals can be assigned roles directly, with assignToMachine / batchAssignToMachines for bulk grants
- MCP server endpoint: agents connect over the standard MCP protocol; credentials and scopes are issued by UIAM
- The agent_tools registry checks whether the caller holds a tool permission before every tool call
- The @RequiresToolPermission annotation puts tool-level authorization in code, not in documentation
- Agent call quotas and rate limits; exceeding quota fails immediately
- End-to-end audit: who delegated to whom, which tool was called, with which permissions — fully replayable
Identity sources & social connectors
uiam-connector · 10-connectorDomestic IM ecosystems and international social accounts behind one connector abstraction.
- WeCom connector: QR-code login and a directory identity source
- WeChat Open Platform connector: WeChat login and user profile retrieval
- WeChat Mini Program connector: mini-program sessions exchanged for a unified identity
- GitHub / Google OAuth2 social login
- A unified connector admin console: configuration, enable/disable and callback governance
- An identity-source abstraction that maps external identities to local identities and identity tags
Audit, governance & operations
uiam-audit · uiam-serverEvery action leaves a trace, and the admin plane runs the platform directly from it.
- Audit logs: structured event records, searchable by principal, tenant and time
- Security alerts: anomalous logins, tenant violations and other risk events flagged separately as SECURITY / FAILURE
- System logs and login history, so users can review their own login footprint
- System initialization and configuration: first-install guidance and runtime switches
- Notification templates and webhooks: event-driven outbound push
- Dictionaries, menus and announcements: the metadata management the admin plane needs
- Quotas and usage: tenant quotas, user quotas and usage statistics
- Sensitive words and IP rules: content compliance and access-source control
API contract
12 representative endpoints. What is listed here is the skeleton of the public contract; full definitions ship with the deployment.
/oauth2/tokenToken endpoint shared by authorization code, client credentials, refresh token and token exchange
/oauth2/authorizeAuthorization endpoint carrying login, MFA step-up and consent
/.well-known/openid-configurationOIDC Discovery: clients discover endpoints and capabilities automatically
/oauth2/jwksPublic key set: business sides verify signatures locally, with no round trip
/oauth2/introspectToken introspection for scenarios that cannot validate offline
/oauth2/revokeToken revocation, triggered by logout, risk control and credential rotation
/api/v1/authn/passkey/registerWebAuthn / passkey registration and credential binding
/api/v1/authz/token-exchangeRFC 8693 delegation and impersonation, with permissions intersected and trimmed
/api/v1/agents/{id}/tools/{tool}/invokeAgent tool-call entry point, checked by @RequiresToolPermission
/api/v1/tenants/{code}/spacesSpace list under a tenant; queries carry the tenant predicate automatically
/api/v1/audit/eventsAudit event retrieval by principal, tenant and time
/api/v1/connectors/{kind}/callbackUnified callback entry point for identity-source connectors
One real call
What an endpoint actually looks like says more than a list of endpoints.
01$ curl -X POST https://id.zhenbei.tech/oauth2/token \02 -d grant_type=urn:ietf:params:oauth:grant-type:token-exchange \03 -d subject_token=$USER_TOKEN \04 -d actor_token=$AGENT_TOKEN \05 -d audience=uniscrm-api0607{ "access_token": "eyJhbGciOiJSUzI1NiIs...",08 "issued_token_type": "urn:ietf:params:oauth:token-type:access_token",09 "expires_in": 900,10 "act": { "sub": "agent:sales-copilot", "principal_type": "machine" } }Contract discipline
An endpoint is a promise, not an exposure of implementation details. These three rules are ones we always keep.
Breaking changes go through a major version, announced one release cycle ahead. A shipped endpoint never changes semantics because of internal refactoring.
Error codes carry semantics instead of a blanket 500, so callers — including AI agents — can decide whether to retry or give up.
Structured data is returned by default instead of human-readable prose, so AI can read it directly — no human screenshotting and relaying.
Modules
5 groups, 14 code modules — all from the real directory structure of the uiam-coplit repository.
uiam-server-kotlin/Principal modelling, org structure and the user lifecycle.
uiam-coreCommon kernel: tenant context, request context, tenant-scoped table registration and query helpers
uiam-core/{api,biz}uiam-deptOrganisation and departments: tree org structure, position accounts, membership and employee–organisation relations
uiam-dept/{api,biz}03-identity / 04-organizationIdentity and organisation data domains: user profiles, identity tags, external members, org relations
db/changelog/migrations/Everything that makes “who is accessing” provable.
uiam-authnAuthentication: password login, verification codes, magic links, passkeys, sessions and login history
uiam-authn/{api,biz}uiam-protocol-oidcOIDC protocol: Discovery, JWKS, the authorization endpoint, the consent page, token issuance and revocation
uiam-protocol/uiam-protocol-oidcuiam-protocol-coreProtocol kernel: client registration, authorization consent, scopes and the token model
uiam-protocol/uiam-protocol-coreuiam-connector-*Identity-source connectors: wecom / weoa / weopen / weapp / github / google
uiam-connector/Decides what one may do, and under which conditions it is not allowed.
uiam-authzAuthorization: roles, permissions, data permissions, token exchange and permission-intersection trimming
uiam-authz/{api,biz}uiam-auditAudit: structured event streams, system logs, security alerts and compliance retention
uiam-audit/{api,biz}13-security-ext / 14-sensitive / 15-ip-ruleSecurity extensions: password history, sensitive words, IP rules, device policies, quotas
db/changelog/migrations/Extends the IAM boundary from people to AI agents.
uiam-agentAgent principals, MCP endpoints, the agent_tools registry and ToolExecutionService
uiam-agent/{api,biz}16-agentAgent data domain: tables for machine principals, delegation chains and tool authorization
db/changelog/migrations/16-agent/The operations plane of a multi-tenant SaaS.
uiam-serverAssembly layer: tenant and space governance, system initialization, system config, dictionaries, menus, announcements, webhooks
uiam-server/uiam-jooqCode generation: Tables / Record types generated from the Liquibase changelog
uiam-jooq/Layered design
From access to runtime — what each layer owns and what it is built with.
OAuth 2.1 / OIDC / Token Exchange (RFC 8693) / JWKS / Discovery / WebAuthn
Users, orgs, service accounts and agents modelled uniformly as four principal types, with subject_type distinguishing USER / MACHINE
RBAC plus data permissions; permissions isolated doubly by tenant / space, with Token Exchange trimming by intersection
The jOOQ TenantScopeVisitListener enforces tenant predicates at the query level, with 45 tenant tables centrally registered
MFA, passkeys, device policies, IP rules, password history, risk alerts, and system JWT key rotation
Structured audit event streams; tenant violations log at SECURITY / FAILURE level
Kotlin 2.2 · Spring Boot 4 · Spring Security 7 · jOOQ · Liquibase · virtual threads
Key flows
The most important paths, unpacked step by step.
Standard OIDC authorization code login
The business system hands the user to UIAM and gets back a verifiable token, not a copy of the user table.
- 1
The application redirects to /oauth2/authorize with client_id, scope and redirect_uri
- 2
UIAM evaluates the session: if not logged in, it shows the login page (password / code / passkey / social)
- 3
When MFA or a device policy matches, a second verification step is inserted; authentication completes only after it passes
- 4
Back at the consent page, the user confirms the authorization scope
- 5
An authorization code is issued, then exchanged for access_token / refresh_token / id_token
- 6
The application validates the token locally against JWKS within P99 — no round trip to the identity centre
Agent delegation chain (token exchange)
When an agent works on a user’s behalf, the token states who acts for whom, and permissions intersect instead of union.
- 1
The agent obtains its own principal token as a MACHINE identity, with principal_type=machine
- 2
It sends a urn:ietf:params:oauth:grant-type:token-exchange request carrying the user token
- 3
TokenExchangeServiceImpl computes application permissions ∩ user permissions and trims to maxPermissionLevel
- 4
The new token carries the act claim recording the delegator; in multi-hop scenarios act nests
- 5
The agent calls business APIs with the new token; the resource side authorizes against the permissions claim
- 6
The whole chain is written to audit, including delegation relations and tool and permission snapshots
Enforced tenant isolation checks
Tenant boundaries are guaranteed not by review but by a listener in the query layer.
- 1
On entry, TenantContextFilter parses tenant_id from the JWT into the context
- 2
If the tenant declared in the request header differs from the JWT, TenantMismatchException (403) is thrown immediately
- 3
At jOOQ execution time, TenantScopeVisitListener checks whether the SQL touches tenant-scoped tables
- 4
Queries missing the tenant predicate are logged as security events or rejected, per configuration
- 5
System-level operations that genuinely cross tenants go through the explicit runAsSystem bypass, and are audited
- 6
UserContext is cleared when the request ends, preventing thread-pool reuse leakage
Tech stack
Scale & benchmarks
These numbers are not estimates — they are read from the code and runtime configuration. Each one states what it actually means, so it cannot be mistaken for marketing.
uiam-coplitJWKS signatures verified locally; business services never round-trip to the identity centre
Central registration + a query-layer listener; a missing predicate can be configured to fail hard
One codebase for MySQL 8 and PostgreSQL, with migrations maintained per dialect
Liquibase versioned; repeat runs produce the same result and failures can roll back
Nested act claims express multi-hop delegation, intersecting permissions at every hop instead of unioning
WeCom / WeChat Open Platform / Mini Programs / WeCom OA / GitHub / Google
Facts you can count in the repository
Every item below can be checked in uiam-coplit: modules, tables, endpoints and capability items. Whether something is “done” is judged by whether these numbers moved.
Security and compliance support points
What UIAM concretely does for security, and where the boundaries are drawn. Every item notes where it is implemented, so you can verify.
A tenant declared in the request header that mismatches the JWT fails with 403; cross-tenant operations must use the explicit bypass channel, and the bypass itself is audited.
TenantMismatchException · runAsSystemPassword policy, password history, account lockout, TOTP MFA, passkeys and magic links combine per tenant and per scenario.
uiam-authn · 13-security-extDevice management, device policies, IP rules and sensitive-word policies form a two-layer defense around login and content.
15-ip-rule · 14-sensitiveSystem JWT signing keys rotate without downtime; old tokens stay verifiable within their validity window.
uiam-protocol-coreAudit events are stored structurally by principal, tenant and time, with security events graded separately for compliance evidence.
uiam-auditAgent credentials are independent of humans; every tool call checks permissions and quota, and all authorization can be revoked instantly.
uiam-agent · agent_toolsWhere the data stops
The data boundary is determined by the product form, not a toggle someone can flip. This is the shared judgement across all four business lines.
The minimum boundary for endpoint products. Data at this layer has no upload path by design — it is not switched off by a toggle.
- All legdger ledger data: encrypted locally, only ciphertext reaches the cloud
- legdger on-device AI statistics and Q&A: inference runs on the device
- NewTool desktop and wasm forms: the algorithm kernel has no IO, so data never leaves the process
- pxc captured traffic: the kernel runs locally and does not pass through third-party services
The boundary for private deployment. Models, vectors, business data and audit records are all deployed inside the customer’s own network.
- Uniclaw memory and knowledge vectors: self-hosted Milvus, never leaving the intranet
- Uniclaw model services: can connect to privately deployed compatible-protocol services
- UIAM identity and audit data: the whole deployment sits inside the customer boundary and can run fully air-gapped
- Uniscrm assets and media: object storage can connect to the customer’s own OSS
- Unilearning courseware and learning records: delivered as a single container, with data under the customer’s control
The only things needing external network access are sync and external channels, and what travels is ciphertext or already-desensitised messages.
- legdger cross-device sync: uploads only the latest ciphertext, and the server keeps no history
- Uniscrm WeCom channel: communicates with official WeCom interfaces and uses official archiving capability
- Uniclaw channels: Feishu / DingTalk push APIs, with content isolated per tenant
- NewTool remote calls: transported over MCP, while the algorithm kernel itself makes no network requests
Company-wide security principles
Whichever business line, these six are the shared floor.
Any constraint that can be baked into the compiler, the framework or the query layer does not go into a document for people to remember. Tenant isolation is enforced by a query-layer listener; domain boundaries are rejected at compile time by Go’s internal mechanism.
jOOQ TenantScopeVisitListener · Go internal 墙Sensitive data stays on the user device or inside the customer network by default. All four business lines support private deployment, and legdger does not even send AI analysis off the device.
legdger 端侧 AI · Uniclaw 自建 Milvus · Unilearning 单容器Agents never share human credentials, servers never hard-code long-lived keys, and endpoint integrations use revocable tokens. Any credential can be revoked on its own without affecting other principals.
UIAM MACHINE 主体 · OSS STS AssumeRole · ledger-cli 令牌Authentication, authorization, tool calls and captured traffic all produce structured records. We keep them not for compliance theatre but so that incidents can be replayed.
uiam-audit · collaboration-logger · pxc 会话记录Delegation is expressed with the act claim — who acts for whom — with permissions intersected at every hop. Audit can answer which user authorized which agent, which tool it called, and with which permissions.
RFC 8693 Token Exchange · agent_tools 注册表Database changes go through versioned migrations that produce the same result on repeat; application releases are single-image swaps, so rollback means switching back to the previous image.
Liquibase · 各域方言迁移 · Docker 单镜像Deploy & integrate
Every product line supports private deployment; the concrete form varies by product.
The default delivery form: the whole identity kernel runs inside the customer’s own network boundary.
- One Spring Boot service + MySQL/PostgreSQL + Redis
- Liquibase versioned migrations — idempotent upgrades, rollback-ready
- No external SaaS dependency; can run fully air-gapped
The same code runs on MySQL and PostgreSQL; dialect differences are absorbed by jOOQ and the migration files.
- application-mysql.yml / application-pg.yml dual profiles
- Migrations maintained in per-dialect directories; released versions are never modified
- jOOQ code generation turns the changelog into a type-safe data access layer
Business systems do not need to change their own user model; they only need to trust tokens issued by UIAM.
- OIDC / OAuth2.1: standard client libraries connect directly
- Tokens validated locally against JWKS — no per-request round trip
- API Key / Application Key for server-to-server scenarios
- MCP for AI agent scenarios
Works with an API gateway to move authentication forward to the traffic entry point.
- Higress integration recipe (docs/integration/higress)
- Token validation completes at the gateway; services only handle post-authorization identity
- Already wired into the Uniclaw and Unilearning product lines
Comparison
The same job, done in different ways. The left column is our choice; the right is the common alternative — the difference is usually not in the feature table but in where the boundary is drawn.
Who feels the difference
Feature lists do not convince people; role perspectives do. Below are the real before-and-after differences for four roles.
Every business system maintains its own account model with inconsistent permission semantics; onboarding a new system means renegotiating login yet again
Standard OIDC integrates once; tokens and the permission model are uniform everywhere, and a new system is just one more registered client
Cannot answer who accessed what, when, as whom; excess privilege is only discovered after the fact
Structured audit event streams connect to SIEM, and tenant violations log straight to SECURITY / FAILURE level
Login logic is re-implemented in every service; one password-policy change touches N repositories
Authentication and authorization converge into the identity kernel; services only read claims from tokens
Departing employees leave permission residue behind, and manual cleanup across systems always misses some
Departure triggers full permission revocation in real time, with no per-system chores
Releases and roadmap
Shipped items state what was delivered, in-progress items what is being built, planned items what is intended. Shipped items are never reversed.
v1.0ReleasedCore kernel- Identity kernel and multi-tenant isolation
- OAuth 2.1 / OIDC authorization server
- RBAC roles and permission management
- MySQL / PostgreSQL dual dialects
v1.2ReleasedAgent IAM- MACHINE principal modelling and service accounts
- RFC 8693 delegation chains with multi-hop propagation
- MCP endpoints and tool-level authorization
- Agent call quotas and rate limits
v1.4In developmentGovernance hardening- Real-time permission-change push (no more waiting for the next login)
- Audit event stream integration with SIEM
- Zero-downtime system JWT key rotation
- A programmable policy engine
v2.0PlannedFederation & policy- Cross-tenant federated identity
- An ABAC policy language
- Cross-border identity data compliance policies
- A third-party application marketplace
Integrations and counterparts
Who UIAM needs to integrate with, and how.
QR-code login and directory sync; the org structure serves directly as the identity source
WeChat login and user profile retrieval, supporting the To-C membership system
Mini-program sessions exchanged for a unified identity, uniting membership across platforms
International social OAuth2 login for internal tools and external collaboration
Authentication moves to the traffic entry point; the gateway validates tokens and forwards identity
Three business lines share one identity kernel; agent credentials and tool authorization are issued by UIAM
Adoption scenarios
How this is used in real business settings.
Multiple subsidiaries and systems under one group share one identity kernel while their data stays mutually invisible.
- Tenants isolate subsidiaries; spaces isolate business systems
- One login carries employees across all internal systems
- Departure revokes all permissions instantly, in real time
Apps, mini programs and web share one membership identity and one set of login methods.
- SMS codes, WeChat and social login converge into one flow
- Membership tags and identity tags maintained in one place
- Open-platform authorization for third-party applications
The agent needs to read orders and send messages — without running wild on a developer’s credentials.
- Agents hold their own MACHINE identity and revocable credentials
- Delegation chains trace which user authorized which agent
- Tool-level authorization decides which endpoints an agent can call
Finance and public-sector scenarios need every access by every person to be explainable.
- Structured audit event streams connect to SIEM
- Sensitive words, IP rules and device policies form layered defenses
- System JWT signing keys rotate without downtime
FAQ
Yes. LDAP solves directory storage; UIAM solves unified authentication under modern protocols (OIDC / OAuth2.1), fine-grained authorization, multi-tenant isolation and agent identity, and it can serve as the control plane above external identity sources.
Hand the complexity of identity, agents and private domain to one governable kernel
Whether you are replacing an existing IAM, building an agent platform, or trying to make private-domain operations actually work — start with a 30-minute architecture call. We will first judge whether this is the kind of problem we are good at, and say so plainly if it is not.