Introductionâ
services.Auth() returns the authentication and authorization namespace. Source plugins access it through services.Auth(), while dynamic plugins declare service: auth in plugin.yaml and access it through the pluginbridge.Default().Auth() client. It contains two sub-capabilities:
Token()handles tenant token selection, tenant switching, and platform admin impersonation token handoff.Authz()handles permission view reading, permission checking, and platform admin checking.
This namespace does not expose the host's JWT signing implementation, session storage, role tables, menu tables, or permission tables. Plugins only initiate token or authorization-related operations through stable domain contracts.
Capability Phase: Runtime
Supported Plugin Types: Source plugins, Dynamic plugins
Capability Designâ
Sub-Capability Systemâ
The Auth capability uses a dual sub-capability model, handling authentication tokens and authorization checks separately:
Token Sub-Capabilityâ
Token() handles tenant token handoff, including host signing, token ID, online session state, and permission cache warm-up. Plugins must still complete business authorization and audit checks before calling.
Authz Sub-Capabilityâ
Authz() handles authorization checks, returning only plugin-visible views or boolean results without exposing host role, menu, or permission table structures. Trusted source plugins that need to replace role permission sets should use services.Admin().Auth().Authz().ReplaceRolePermissions.
Dynamic Plugin Identity Acquisitionâ
Dynamic plugins declare service: auth in plugin.yaml and access the Token() sub-capability through the pluginbridge.Default().Auth() client. Authentication results for dynamic route requests are also injected into BridgeRequestEnvelopeV1.Identity by the host.
Interface Definitionsâ
Token Sub-Capability Interfaceâ
| Method | Description |
|---|---|
SelectTenant | Consumes pre-login PreToken, issues AccessToken and RefreshToken bound to the target tenant |
SwitchTenant | Validates target tenant membership, revokes current token and issues new tenant token |
IssueImpersonationToken | Issues an impersonation token for platform admin to enter target tenant |
RevokeImpersonationToken | Validates and revokes an impersonation access token |
Authz Sub-Capability Interfaceâ
| Method | Description |
|---|---|
BatchGetPermissions | Batch-reads visible permission views; missing results don't reveal specific reasons |
BatchHasPermissions | Batch-checks whether the current operator has each permission key within the current scope |
HasPermission | Checks whether the current operator has a specific permission within the current scope |
IsPlatformAdmin | Checks whether a specific user has the platform full-data role |
Dynamic Plugin Interfaceâ
Dynamic plugins declare authorized methods through hostServices.auth:
| Dynamic Method | Description |
|---|---|
tenant.select | Consumes pre-login PreToken, issues token bound to target tenant |
tenant.switch | Validates target tenant membership, revokes current token and issues new tenant token |
impersonation_token.issue | Issues impersonation token for platform admin to enter target tenant |
impersonation_token.revoke | Validates and revokes impersonation access token |
Capability Usageâ
Source Plugin Usageâ
Source plugins access Token() and Authz() sub-capabilities through services.Auth():
// Tenant selection: issue token bound to target tenant
tenantToken, err := services.Auth().Token().SelectTenant(ctx, token.SelectTenantInput{
PreToken: preToken,
TenantID: tenantID,
})
// Tenant switching: validate membership and issue new token
tenantToken, err = services.Auth().Token().SwitchTenant(ctx, token.SwitchTenantInput{
BearerToken: bearerToken,
TenantID: targetTenantID,
})
// Batch permission check
hasMap, err := services.Auth().Authz().BatchHasPermissions(ctx, capabilityCtx, permissionKeys)
// Single permission check
has, err := services.Auth().Authz().HasPermission(ctx, capabilityCtx, permissionKey)
// Platform admin check
isAdmin, err := services.Auth().Authz().IsPlatformAdmin(ctx, capabilityCtx, userID)
Trusted source plugins replacing role permission sets:
err := services.Admin().Auth().Authz().ReplaceRolePermissions(ctx, capabilityCtx, roleID, permissions)
Dynamic Plugin Usageâ
Dynamic plugins declare auth service and authorized methods in plugin.yaml:
hostServices:
- service: auth
methods:
- tenant.select
- tenant.switch
Dynamic plugins call through the pluginbridge.Default().Auth() client:
authSvc := pluginbridge.Default().Auth()
// Tenant selection: issue token bound to target tenant
tenantToken, err := authSvc.Token().SelectTenant(ctx, token.SelectTenantInput{
PreToken: preToken,
TenantID: tenantID,
})
// Tenant switching: validate membership and issue new token
tenantToken, err = authSvc.Token().SwitchTenant(ctx, token.SwitchTenantInput{
BearerToken: bearerToken,
TenantID: targetTenantID,
})
Design Constraintsâ
- Plugins do not directly issue
JWTs. Signing, keys, expiration policies, and session registration are controlled by the host authentication service. - Tenant switching must be validated.
SwitchTenantvalidates membership and revokes old tokens; clients must use the new token for subsequent requests. - Authorization reads don't expose permission tables.
Authz()only returns plugin-visible views or boolean results, not host role, menu, or permission table structures. - Impersonation tokens require caller audit. Plugins should log who is impersonating into which tenant and for what reason.