OpenIddict 模块(专业版)
您必须拥有 ABP 团队版或更高许可证 才能使用此模块。
该模块为 OpenIddict 库提供了集成和管理功能;
- 基于 OpenIddict-core 库构建。
- 管理系统中的应用程序和 API 范围。
- 为客户端设置权限。
有关模块功能的概述,请参见模块描述页面。
如何安装
从 6.0.0-rc1 版本开始,OpenIddict 已在 启动模板 中预安装。因此,无需手动安装。您也可以按照 逐步迁移到 OpenIddict 指南 迁移现有应用程序。
包
此模块遵循 模块开发最佳实践指南,由多个 NuGet 和 NPM 包组成。如果您想了解这些包及其之间的关系,请参阅该指南。
您可以访问Identity 模块包列表页面查看与此模块相关的包列表。
用户界面
菜单项
OpenIddict 模块在“管理”菜单项下的“主”菜单中添加了以下项目:
- 应用程序:应用程序管理页面。
- 范围:范围管理页面。
OpenIddictProMenus 类包含了菜单项名称的常量。
页面
应用程序管理
应用程序页面用于管理 OpenIddict 应用程序。一个 application 代表可以从您的认证服务器请求令牌的托管应用程序。
您可以在此页面创建新应用程序或编辑现有应用程序:
API 范围管理
OpenIddict 模块允许管理 API 范围。要允许应用程序为 API 请求访问令牌,您需要定义 API 范围。
您可以在此页面创建新的 API 资源或编辑现有的 API 资源:
数据种子
当您运行 .DbMigrator 应用程序时,此模块会向数据库添加一些初始数据(参见数据种子系统):
- 创建标准的身份资源,包括角色、个人资料、电话、openid、电子邮件和地址。
- 创建应用程序。
- 创建 API 范围。
您可以在应用程序管理页面中删除或编辑已创建的应用程序。
选项
OpenIddictBuilder
OpenIddictBuilder 可以在您的 OpenIddict 模块 的 PreConfigureServices 方法中配置。
示例:
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictBuilder>(builder =>
{
//在此设置选项...
});
}
OpenIddictBuilder 包含多种扩展方法来配置 OpenIddict 服务:
AddServer()在 DI 容器中注册 OpenIddict 令牌服务器服务。包含OpenIddictServerBuilder配置。AddCore()在 DI 容器中注册 OpenIddict 核心服务。包含OpenIddictCoreBuilder配置。AddValidation()在 DI 容器中注册 OpenIddict 令牌验证服务。包含OpenIddictValidationBuilder配置。
OpenIddictCoreBuilder
OpenIddictCoreBuilder 包含用于配置 OpenIddict 核心服务的扩展方法。
示例:
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictCoreBuilder>(builder =>
{
//在此设置选项...
});
}
这些服务包括:
- 添加
ApplicationStore、AuthorizationStore、ScopeStore、TokenStore。 - 替换
ApplicationManager、AuthorizationManager、ScopeManager、TokenManager。 - 替换
ApplicationStoreResolver、AuthorizationStoreResolver、ScopeStoreResolver、TokenStoreResolver。 - 设置
DefaultApplicationEntity、DefaultAuthorizationEntity、DefaultScopeEntity、DefaultTokenEntity。
OpenIddictServerBuilder
OpenIddictServerBuilder 包含用于配置 OpenIddict 服务器服务的扩展方法。
示例:
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictServerBuilder>(builder =>
{
//在此设置选项...
});
}
这些服务包括:
- 注册声明、范围。
- 设置
IssuerURI,该 URI 用作从发现端点返回的端点 URI 的基础地址。 - 添加开发签名密钥、加密/签名密钥、凭据和证书。
- 添加/删除事件处理器。
- 启用/禁用授权类型。
- 设置认证服务器端点 URI。
OpenIddictValidationBuilder
OpenIddictValidationBuilder 包含用于配置 OpenIddict 验证服务的扩展方法。
示例:
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictValidationBuilder>(builder =>
{
//在此设置选项...
});
}
这些服务包括:
AddAudiences()用于资源服务器。SetIssuer()URI,用于在使用提供者发现时确定 OAuth 2.0/OpenID Connect 配置文档的实际位置。SetConfiguration()用于配置OpenIdConnectConfiguration。UseIntrospection()使用内省而不是本地/直接验证。- 添加加密密钥、凭据和证书。
- 添加/删除事件处理器。
SetClientId()用于在与远程授权服务器通信时设置客户端标识符client_id(例如用于内省)。SetClientSecret()用于在与远程授权服务器通信时设置标识符client_secret(例如用于内省)。EnableAuthorizationEntryValidation()启用授权验证,通过为每个 API 请求进行数据库调用来确保access token仍然有效。*注意:*这可能会对性能产生负面影响,并且只能与基于 OpenIddict 的授权服务器一起使用。EnableTokenEntryValidation()启用授权验证,通过为每个 API 请求进行数据库调用来确保access token仍然有效。*注意:*这可能会对性能产生负面影响,并且在 OpenIddict 服务器配置为使用引用令牌时是必需的。UseLocalServer()注册 OpenIddict 验证/服务器集成服务。UseAspNetCore()在 DI 容器中为 ASP.NET Core 注册 OpenIddict 验证服务。
内部结构
领域层
聚合
OpenIddictApplication
OpenIddictApplications 表示可以从您的 OpenIddict 服务器请求令牌的应用程序。
OpenIddictApplications(聚合根):表示一个 OpenIddict 应用程序。ClientId(字符串):与当前应用程序关联的客户端标识符。ClientSecret(字符串):与当前应用程序关联的客户端密钥。出于安全原因,可能被哈希或加密。ConsentType(字符串):与当前应用程序关联的同意类型。DisplayName(字符串):与当前应用程序关联的显示名称。DisplayNames(字符串):与当前应用程序关联的本地化显示名称,序列化为 JSON 对象。Permissions(字符串):与当前应用程序关联的权限,序列化为 JSON 数组。PostLogoutRedirectUris(字符串):与当前应用程序关联的注销回调 URL,序列化为 JSON 数组。Properties(字符串):与当前应用程序关联的附加属性,序列化为 JSON 对象或 null。RedirectUris(字符串):与当前应用程序关联的回调 URL,序列化为 JSON 数组。Requirements(字符串):与当前应用程序关联的要求。Type(字符串):与当前应用程序关联的应用程序类型。ClientUri(字符串):关于客户端的更多信息的 URI。LogoUri(字符串):客户端徽标的 URI。
OpenIddictAuthorization
OpenIddictAuthorizations 用于保存允许的范围、授权流程类型。
OpenIddictAuthorization(聚合根):表示一个 OpenIddict 授权。ApplicationId(Guid?):与当前授权关联的应用程序。Properties(字符串):与当前授权关联的附加属性,序列化为 JSON 对象或 null。Scopes(字符串):与当前授权关联的范围,序列化为 JSON 数组。Status(字符串):当前授权的状态。Subject(字符串):与当前授权关联的主题。Type(字符串):当前授权的类型。
OpenIddictScope
OpenIddictScopes 用于保存资源的范围。
OpenIddictScope(聚合根):表示一个 OpenIddict 范围。Description(字符串):与当前范围关联的公共描述。Descriptions(字符串):与当前范围关联的本地化公共描述,序列化为 JSON 对象。DisplayName(字符串):与当前范围关联的显示名称。DisplayNames(字符串):与当前范围关联的本地化显示名称,序列化为 JSON 对象。Name(字符串):与当前范围关联的唯一名称。Properties(字符串):与当前范围关联的附加属性,序列化为 JSON 对象或 null。Resources(字符串):与当前范围关联的资源,序列化为 JSON 数组。
OpenIddictToken
OpenIddictTokens 用于持久化应用程序令牌。
OpenIddictToken(聚合根):表示一个 OpenIddict 令牌。ApplicationId(Guid?):与当前令牌关联的应用程序。AuthorizationId(Guid?):与当前令牌关联的授权。CreationDate(DateTime?):当前令牌的 UTC 创建日期。ExpirationDate(DateTime?):当前令牌的 UTC 过期日期。Payload(字符串):当前令牌的有效负载(如果适用)。仅用于引用令牌,出于安全原因可能被加密。Properties(字符串):与当前令牌关联的附加属性,序列化为 JSON 对象或 null。RedemptionDate(DateTime?):当前令牌的 UTC 兑换日期。ReferenceId(字符串):与当前令牌关联的引用标识符(如果适用)。仅用于引用令牌,出于安全原因可能被哈希或加密。Status(字符串):当前令牌的状态。Subject(字符串):与当前令牌关联的主题。Type(字符串):当前令牌的类型。
存储
此模块实现了 OpenIddict 存储:
IAbpOpenIdApplicationStoreIOpenIddictAuthorizationStoreIOpenIddictScopeStoreIOpenIddictTokenStore
存储库
此模块中定义了以下自定义存储库:
IOpenIddictApplicationRepositoryIOpenIddictAuthorizationRepositoryIOpenIddictScopeRepositoryIOpenIddictTokenRepository
领域服务
此模块不包含任何领域服务,但重写了以下服务:
AbpApplicationManager用于填充/获取包含ClientUri和LogoUri的AbpApplicationDescriptor信息。
设置
此模块未定义任何设置。
应用层
应用服务
ApplicationAppService(实现IApplicationAppService):实现应用程序管理 UI 的用例。ScopeAppService(实现IScopeAppService):实现 API 范围管理 UI 的用例。
数据库提供程序
通用
表/集合前缀与架构
默认情况下,所有表/集合都使用 OpenIddict 前缀。如果您需要更改表前缀或设置架构名称(如果您的数据库提供程序支持),请在 AbpOpenIddictDbProperties 类上设置静态属性。
连接字符串
此模块使用 AbpOpenIddict 作为连接字符串名称。如果您未定义具有此名称的连接字符串,它将回退到 Default 连接字符串。
有关详细信息,请参阅连接字符串文档。
Entity Framework Core
表
- OpenIddictApplications
- OpenIddictAuthorizations
- OpenIddictScopes
- OpenIddictTokens
MongoDB
集合
- OpenIddictApplications
- OpenIddictAuthorizations
- OpenIddictScopes
- OpenIddictTokens
权限
有关为此模块定义的所有权限,请参阅 AbpOpenIddictProPermissions 类成员。
ASP.NET Core 模块
此模块集成了 ASP.NET Core,为四种协议提供了内置的 MVC 控制器。它使用 OpenIddict 的 直通模式。
AuthorizeController -> connect/authorize
TokenController -> connect/token
LogoutController -> connect/logout
UserInfoController -> connect/userinfo
AbpOpenIddictAspNetCoreOptions
AbpOpenIddictAspNetCoreOptions 可以在您的 OpenIddict 模块 的 PreConfigureServices 方法中配置。
示例:
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
//在此设置选项...
});
AbpOpenIddictAspNetCoreOptions 属性:
UpdateAbpClaimTypes(default: true):更新AbpClaimTypes以兼容 Openiddict 声明。AddDevelopmentEncryptionAndSigningCertificate(default: true):注册(并在必要时生成)用户特定的开发加密/开发签名证书。
自动移除孤立的令牌/授权
自动移除孤立令牌/授权的后台任务。可以通过 TokenCleanupOptions 来配置管理它。
TokenCleanupOptions 可以在您的 OpenIddict 模块 的 PreConfigureServices 方法中配置。
示例:
PreConfigure<TokenCleanupOptions>(options =>
{
//在此设置选项...
});
TokenCleanupOptions 属性:
IsCleanupEnabled(默认:true):启用/禁用令牌清理。CleanupPeriod(默认:3,600,000 毫秒):设置清理周期。DisableAuthorizationPruning:设置一个布尔值,指示是否应禁用授权修剪。DisableTokenPruning:设置一个布尔值,指示是否应禁用令牌修剪。MinimumAuthorizationLifespan(默认:14 天):设置授权必须具有的最短生命周期才能被修剪。不能少于 10 分钟。MinimumTokenLifespan(默认:14 天):设置令牌必须具有的最短生命周期才能被修剪。不能少于 10 分钟。
在 Access_token 和 Id_token 中更新声明
声明主体工厂 可用于向 ClaimsPrincipal 添加/删除声明。
AbpDefaultOpenIddictClaimDestinationsProvider 服务将默认将 Name、Email 和 Role 类型的声明添加到 access_token 和 id_token 中,其他声明默认仅添加到 access_token,并移除 Identity 的 SecurityStampClaimType 秘密声明。
创建一个继承自 IAbpOpenIddictClaimDestinationsProvider 的服务并将其添加到 DI 中,以完全控制声明的目标。
public class MyClaimDestinationsProvider : IAbpOpenIddictClaimDestinationsProvider, ITransientDependency
{
public virtual Task SetDestinationsAsync(AbpOpenIddictClaimDestinationsProviderContext context)
{
// ...
return Task.CompletedTask;
}
}
Configure<AbpOpenIddictClaimDestinationsOptions>(options =>
{
options.ClaimDestinationsProvider.Add<MyClaimDestinationsProvider>();
});
详细资料请参阅:OpenIddict 声明目标
禁用访问令牌加密
ABP 默认为兼容性禁用了 access token encryption,如果需要可以手动启用。
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<OpenIddictServerBuilder>(builder =>
{
builder.Configure(options => options.DisableAccessTokenEncryption = false);
});
}
禁用传输安全要求
默认情况下,OpenIddict 要求所有端点使用 HTTPS。如果需要,您可以禁用它。您只需配置 OpenIddictServerAspNetCoreOptions 并将 DisableTransportSecurityRequirement 设置为 true:
Configure<OpenIddictServerAspNetCoreOptions>(options =>
{
options.DisableTransportSecurityRequirement = true;
});
请求/响应过程
OpenIddict.Server.AspNetCore 添加了一个认证方案(Name: OpenIddict.Server.AspNetCore, handler: OpenIddictServerAspNetCoreHandler)并实现了 IAuthenticationRequestHandler 接口。
它将在 AuthenticationMiddleware 中首先执行,并可以短路当前请求。否则,将调用 DefaultAuthenticateScheme 并继续执行管道。
OpenIddictServerAspNetCoreHandler 将调用各种内置处理器(处理请求和响应),处理器将根据上下文处理或跳过与其无关的逻辑。
令牌请求示例:
POST /connect/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=password&
client_id=AbpApp&
client_secret=1q2w3e*&
username=admin&
password=1q2w3E*&
scope=AbpAPI offline_access
此请求将由各种处理器处理。它们将确认请求的端点类型,检查 HTTP/HTTPS,验证请求参数(client、scope 等)是否有效并存在于数据库中,等等。进行各种协议检查。并构建一个 OpenIddictRequest 对象。如果有任何错误,可能会设置响应内容并直接短路当前请求。
如果一切正常,请求将转到我们的处理控制器(例如 TokenController),此时我们可以从 HTTP 请求中获取 OpenIddictRequest 对象。其余处理将基于此对象进行。
检查请求中的 username 和 password。如果正确,则创建一个 ClaimsPrincipal 对象并返回一个 SignInResult,它使用 OpenIddict.Validation.AspNetCore 认证方案名称,将调用 OpenIddictServerAspNetCoreHandler 进行处理。
OpenIddictServerAspNetCoreHandler 进行一些检查以生成 JSON 并替换 HTTP 响应内容。
ForbidResult 和 ChallengeResult 的处理方式同上。
如果您需要自定义 OpenIddict,则需要替换/删除/添加新的处理器,并使其以正确的顺序执行。
请参考: https://documentation.openiddict.com/guides/index.html#events-model
PKCE
https://documentation.openiddict.com/configuration/proof-key-for-code-exchange.html
设置令牌生命周期
更新 AuthServerModule(或者如果没有分层/独立的认证服务器,则更新 HttpApiHostModule)文件的 PreConfigureServices 方法:
PreConfigure<OpenIddictServerBuilder>(builder =>
{
builder.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(30));
builder.SetAccessTokenLifetime(TimeSpan.FromMinutes(30));
builder.SetIdentityTokenLifetime(TimeSpan.FromMinutes(30));
builder.SetRefreshTokenLifetime(TimeSpan.FromDays(14));
});
刷新令牌
要使用刷新令牌,它必须得到 OpenIddictServer 的支持,并且应用程序必须请求 refresh_token。
配置 OpenIddictServer
有两种方法允许应用程序使用 refresh_token。
从 OpenIddictDataSeedContributor,在
CreateApplicationAsync方法中将OpenIddictConstants.GrantTypes.RefreshToken添加到授权类型中:await CreateApplicationAsync( ... grantTypes: new List<string> //混合流 { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.RefreshToken, }, ...注意: 如果您已经生成了数据库,则需要重新创建此客户端。
或者从 OpenIddict 管理 UI,编辑您的应用程序并
允许刷新令牌流:
注意: Angular 应用程序已配置为使用
refresh_token。
配置应用程序
您需要请求 offline_access scope 才能接收 refresh_token。
在 Razor/MVC、Blazor-Server 应用程序中,将 options.Scope.Add("offline_access"); 添加到 OpenIdConnect 选项中。这些应用程序模板默认使用 cookie 身份验证,并且默认的 cookie 过期选项设置为:
.AddCookie("Cookies", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(365);
})
Cookie ExpireTimeSpan 会忽略 access_token 的过期时间,如果其设置的值高于 refresh_token 生命周期,那么过期的 access_token 仍然有效。建议保持 Cookie ExpireTimeSpan 与 刷新令牌生命周期 相同,这样新令牌将被持久化到 cookie 中。
在 Blazor wasm 应用程序中,将 options.ProviderOptions.DefaultScopes.Add("offline_access"); 添加到 AddOidcAuthentication 选项中。
在 Angular 应用程序中,将 offline_access 添加到 environment.ts 文件中的 oAuthConfig 范围中。(Angular 应用程序已具备此配置)。
抠丁客







