feat(identity): 接入认证中心多租户登录
支持 Manifest V2 动态 tid 验证、Tenant Context 同步和租户内 JIT 投影,并保留 Manifest V1 与旧 Session 兼容。\n\n增加 tenantHint、租户切换、普通注册关闭及 application/principal/tenant 两级 SSF 撤销;迁移、定向安全测试和本地双租户跨仓 E2E 已通过。\n\nrelease_required=true;未执行 Release、Staging 或真实链路。
This commit is contained in:
@@ -176,3 +176,53 @@ func TestNewDraftAllowsLoopbackHTTPOnlyInLocalEnvironments(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyManifestV2RemovesFixedTenantMappingWhileV1StillRequiresIt(t *testing.T) {
|
||||
draft, err := NewDraft(PairingInput{
|
||||
AuthCenterURL: "https://auth.example.com", PublicBaseURL: "https://api.example.com",
|
||||
WebBaseURL: "https://gateway.example.com",
|
||||
}, "production")
|
||||
if err != nil {
|
||||
t.Fatalf("multi-tenant pairing draft rejected: %v", err)
|
||||
}
|
||||
applied, err := ApplyManifest(draft, ManifestApplication{
|
||||
AppEnv: "production", MachineCredentialRef: "identity-machine-example",
|
||||
SessionEncryptionKeyRef: "identity-session-example",
|
||||
Manifest: ManifestV2{
|
||||
SchemaVersion: 2, TenantMode: "multi_tenant", Issuer: "https://auth.example.com/issuer/shared",
|
||||
ApplicationID: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
|
||||
Audience: "urn:easyai:resource:bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
|
||||
Capabilities: []string{"oidc_login", "api_access", "machine_to_machine", "token_introspection", "session_revocation"},
|
||||
Scopes: []string{"openid", "gateway.access"},
|
||||
Clients: ManifestClients{
|
||||
BrowserLogin: &ManifestClient{ClientID: "browser"}, MachineToMachine: &ManifestClient{ClientID: "service"},
|
||||
},
|
||||
TenantContext: &ManifestTenantContext{
|
||||
Endpoint: "https://auth.example.com/api/v1/runtime/tenants/{tenantId}",
|
||||
Audience: "urn:easyai:auth-center:tenant-context", Scope: "tenant.context.read",
|
||||
},
|
||||
SecurityEvents: &ManifestSecurityEvents{
|
||||
TransmitterIssuer: "https://auth.example.com/ssf",
|
||||
ConfigurationEndpoint: "https://auth.example.com/.well-known/ssf-configuration/ssf",
|
||||
Audience: "urn:easyai:ssf:receiver:bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if applied.SchemaVersion != 2 || applied.TenantMode != "multi_tenant" || applied.TenantID != "" ||
|
||||
applied.LocalTenantKey != "" || applied.TenantContextEndpoint == "" {
|
||||
t.Fatalf("unexpected multi-tenant revision: %#v", applied)
|
||||
}
|
||||
|
||||
v1Draft := draft
|
||||
v1Draft.ID = "v1-draft"
|
||||
if _, err := ApplyManifest(v1Draft, ManifestApplication{AppEnv: "production", Manifest: ManifestV1{
|
||||
SchemaVersion: 1, Issuer: "https://auth.example.com/issuer/shared",
|
||||
TenantID: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", ApplicationID: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
|
||||
Capabilities: []string{}, Scopes: []string{}, Clients: ManifestClients{},
|
||||
}}); err == nil {
|
||||
t.Fatal("Manifest V1 without a fixed local tenant mapping was accepted")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user