Skip to main content
Version: 0.5.x

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​

MethodDescription
SelectTenantConsumes pre-login PreToken, issues AccessToken and RefreshToken bound to the target tenant
SwitchTenantValidates target tenant membership, revokes current token and issues new tenant token
IssueImpersonationTokenIssues an impersonation token for platform admin to enter target tenant
RevokeImpersonationTokenValidates and revokes an impersonation access token

Authz Sub-Capability Interface​

MethodDescription
BatchGetPermissionsBatch-reads visible permission views; missing results don't reveal specific reasons
BatchHasPermissionsBatch-checks whether the current operator has each permission key within the current scope
HasPermissionChecks whether the current operator has a specific permission within the current scope
IsPlatformAdminChecks whether a specific user has the platform full-data role

Dynamic Plugin Interface​

Dynamic plugins declare authorized methods through hostServices.auth:

Dynamic MethodDescription
tenant.selectConsumes pre-login PreToken, issues token bound to target tenant
tenant.switchValidates target tenant membership, revokes current token and issues new tenant token
impersonation_token.issueIssues impersonation token for platform admin to enter target tenant
impersonation_token.revokeValidates 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. SwitchTenant validates 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.