Skip to content
Bitzsoft.Integrationsbitzsoft.integrations

Concept

IdentityProvider 身份提供者

身份提供者域完整手册——IIdentityProviderService 13 方法、用户 CRUD 与激活/停用/重置密码、用户组管理、Okta SSWS 与 Keycloak client_credentials 两种鉴权模型。

Last updated

IdentityProvider 域统一了身份提供者(IdP)的用户与用户组管理能力。Okta 和 Keycloak 两家供应商共享同一个 IIdentityProviderService 接口,但鉴权机制完全不同:Okta 用 API Token(SSWS Bearer),Keycloak 用 client_credentials 换 OAuth2 token 并经 TokenManager 缓存刷新。

域结构

Bitzsoft.Integrations.IdentityProvider ← 抽象层
├── Bitzsoft.Integrations.IdentityProvider.Okta ← Okta(API Token SSWS)
├── Bitzsoft.Integrations.IdentityProvider.Keycloak ← Keycloak(client_credentials)
└── Bitzsoft.Integrations.IdentityProvider.All ← 聚合包

标准三层包模式。

统一接口(13 方法)

IIdentityProviderService 围绕”用户(User)“和”用户组(Group)“两个核心概念组织,共 13 个成员:

public interface IIdentityProviderService
{
string ProviderName { get; }
// 用户生命周期(5)
Task<IdentityUser> CreateUserAsync(CreateUserRequest request, CancellationToken cancellationToken = default);
Task<IdentityUser> GetUserAsync(string userId, CancellationToken cancellationToken = default);
Task<IdentityUser> UpdateUserAsync(string userId, UpdateUserRequest request, CancellationToken cancellationToken = default);
Task DeleteUserAsync(string userId, CancellationToken cancellationToken = default);
Task<List<IdentityUser>> ListUsersAsync(ListUsersRequest request, CancellationToken cancellationToken = default);
// 账户状态与凭证(3)
Task ActivateUserAsync(string userId, CancellationToken cancellationToken = default);
Task DeactivateUserAsync(string userId, CancellationToken cancellationToken = default);
Task ResetPasswordAsync(string userId, ResetPasswordRequest request, CancellationToken cancellationToken = default);
// 用户组(5)
Task<IdentityGroup> CreateGroupAsync(CreateGroupRequest request, CancellationToken cancellationToken = default);
Task<IdentityGroup> UpdateGroupAsync(string groupId, UpdateGroupRequest request, CancellationToken cancellationToken = default);
Task DeleteGroupAsync(string groupId, CancellationToken cancellationToken = default);
Task<List<IdentityGroup>> ListGroupsAsync(CancellationToken cancellationToken = default);
Task AddUserToGroupAsync(string userId, string groupId, CancellationToken cancellationToken = default);
}

查询类方法(Create / Get / Update / List)抛异常表达失败;账户状态与用户组操作多为无返回的 Task,失败同样抛 IdentityProviderException

鉴权模型

两家供应商使用截然不同的鉴权机制:

供应商鉴权机制Token 注入Token 刷新
OktaAPI Token(SSWS,Static Token)Authorization: SSWS {apiToken}静态令牌,不刷新(管理员手动轮换)
KeycloakOAuth2 client_credentials(Client Id + Secret)Authorization: Bearer {token}POST /realms/{realm}/protocol/openid-connect/token(TokenManager 缓存)

Keycloak 的 TokenManager

Keycloak 的 token 有过期时间,由注册为 Singleton 的 TokenManager 负责缓存刷新,采用双重检查锁模式:快速路径无锁检查缓存、进锁后二次校验、提前 5 分钟刷新。HttpClient 检测到 401 时清缓存触发下次自动刷新。Okta 因使用静态 API Token,无需 TokenManager。

供应商清单

供应商Provider IDAPI 基地址StabilityDI 方法
Oktaokta{your-domain}.okta-tenant.com/apiPreviewAddOktaIdentityProvider()
Keycloakkeycloak{your-host}/realms/{realm}PreviewAddKeycloakIdentityProvider()

两家具备完整的用户与用户组管理能力,均标记为 Preview

注册

单厂商

// ① Okta(API Token SSWS)
builder.Services.AddOktaIdentityProvider(builder.Configuration.GetSection("IdentityProvider:Okta"));
// ② Keycloak(client_credentials + TokenManager)
builder.Services.AddKeycloakIdentityProvider(builder.Configuration.GetSection("IdentityProvider:Keycloak"));

全量聚合

builder.Services.AddBitzsoftIdentityProviderAll(builder.Configuration, "IdentityProvider");

按配置节存在性自动注册,appsettings.json 只需写出启用的供应商:

{
"IdentityProvider": {
"Okta": {
"Domain": "https://your-org.okta.com",
"ApiToken": "00...",
"ApiVersion": "1"
},
"Keycloak": {
"ServerUrl": "https://your-host/auth",
"Realm": "master",
"ClientId": "admin-cli",
"ClientSecret": "..."
}
}
}

消费

用户生命周期

public class UserProvisioningService(IIntegrationProviderResolver<IIdentityProviderService> providers)
{
public async Task<IdentityUser> OnboardAsync(string vendor, string email, string firstName, string lastName)
{
var idp = providers.GetRequired(vendor); // "okta" / "keycloak"
return await idp.CreateUserAsync(new CreateUserRequest
{
Email = email,
FirstName = firstName,
LastName = lastName,
IsActive = true,
});
}
}

激活/停用与重置密码

// 停用离职用户
await idp.DeactivateUserAsync(userId);
// 重置密码(临时密码,下次登录强制改)
await idp.ResetPasswordAsync(userId, new ResetPasswordRequest
{
NewPassword = tempPassword,
Temporary = true,
});

用户组管理

// 创建部门用户组并加入成员
var group = await idp.CreateGroupAsync(new CreateGroupRequest
{
Name = "engineering",
Description = "工程团队",
});
await idp.AddUserToGroupAsync(userId, group.Id);

多厂商路由

public class IdpRouter(IIntegrationProviderResolver<IIdentityProviderService> providers)
{
public async Task<IdentityUser> GetUserAsync(string source, string userId)
{
var idp = providers.GetRequired(source); // "okta" / "keycloak"
return await idp.GetUserAsync(userId);
}
}

相关

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%