OpenIddict 介绍
一.什么是OpenIddict
OpenIddict 是一个开源的通用框架 ,用于在任何 ASP.NET Core 2.1(及更高版本)和遗留 ASP.NET 4.6.1(及更高版本)应用程序中构建符合标准的 OAuth 2.0/OpenID Connect 服务器。
OpenIddict 授权服务器中集成包括: 直通模式和事件模型。OpenIddict允许自定义控制器的Action和自定义中间件,来处理授权、注销、令牌请求。
与OpenIddict 的集成通常是通过直通模式来处理控制器操作或最小API处理程序中的请求,对于更复杂的场景直接使用其高级事件模型来完成。
OpenIddict 为 授权服务器实现了一个强大的基于事件的模型:请求处理逻辑的每个部分都被实现为一个事件处理程序,可以将其删除、移动到管道中的不同位置或由自定义处理程序替换以覆盖OpenIddict使用的默认逻辑。
二.应用权限
OpenIddict 内置了“应用程序权限”的功能,允许控制和限制每个注册的客户端应用程序能够使用OAuth 2.0/OpenID Connect功能,目前支持4类权限:
1)Endpoint permissions(端点权限)
2)Grant type permissions(授予类型权限)
3)Scope permissions(范围权限)
4)Response type permissions(响应类型权限)
这四种权限概念,其实在keycloak或ids4中都有体现。
2.1 端点权限
是指限制客户端应用程序可以使用的端点。
权限端点包括:
端点 | 枚举类型 |
Authorization(授权) | OpenIddictConstants.Permissions.Endpoints.Authorization |
Introspection(内省) | OpenIddictConstants.Permissions.Endpoints.Introspection |
Logout/end session(注销/结束会话) | OpenIddictConstants.Permissions.Endpoints.Logout |
Revocation(撤消) | OpenIddictConstants.Permissions.Endpoints.Revocation |
Token(令牌) | OpenIddictConstants.Permissions.Endpoints.Token |
在以下示例中,mvc
允许应用程序使用授权、注销和令牌端点,但在尝试发送内省或撤销请求时会出错:
下面是手动用代码创建一个mvc的客户端,分配权限,在生产中需要实现动态配置客户端。
if (await manager.FindByClientIdAsync("mvc") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "mvc", ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654", DisplayName = "MVC client application", PostLogoutRedirectUris = { new Uri("http://localhost:53507/signout-callback-oidc") }, RedirectUris = { new Uri("http://localhost:53507/signin-oidc") }, Permissions = { OpenIddictConstants.Permissions.Endpoints.Authorization, OpenIddictConstants.Permissions.Endpoints.Logout, OpenIddictConstants.Permissions.Endpoints.Token } }); }
禁用端点权限,如果不想使用端点权限,请调用options.IgnoreEndpointPermissions()
以忽略它们:
services.AddOpenIddict() .AddServer(options => { options.IgnoreEndpointPermissions(); });
2.2 授予类型权限
是指:限制允许客户端应用程序使用的授予类型,也就是授权许可类型。
Grant Type | 枚举类型 |
Authorization code(授权码类型) | OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode |
Client credentials(客户端凭据类型) | OpenIddictConstants.Permissions.GrantTypes.ClientCredentials |
Implicit (隐式类型) | OpenIddictConstants.Permissions.GrantTypes.Implicit |
Password(资源拥有者类型 ) | OpenIddictConstants.Permissions.GrantTypes.Password |
Refresh token(刷新token) | OpenIddictConstants.Permissions.GrantTypes.RefreshToken |
例如下面示例中,postman客户端只能使用Authorization code许可类型,console客户端使用password和refresh_token许可类型。下面也是通过手动用代码创建客户端。
if (await manager.FindByClientIdAsync("postman") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "postman", DisplayName = "Postman", RedirectUris = { new Uri("https://www.getpostman.com/oauth2/callback") }, Permissions = { OpenIddictConstants.Permissions.Endpoints.Authorization, OpenIddictConstants.Permissions.Endpoints.Token, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode } }); } if (await manager.FindByClientIdAsync("console") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "console", DisplayName = "Console", Permissions = { OpenIddictConstants.Permissions.Endpoints.Token, OpenIddictConstants.Permissions.GrantTypes.Password, OpenIddictConstants.Permissions.GrantTypes.RefreshToken } }); }
如果不想使用授予类型的权限,请调用options.IgnoreGrantTypePermissions()
以忽略它们:
services.AddOpenIddict() .AddServer(options => { options.IgnoreGrantTypePermissions(); });
2.3 范围权限
是指:允许客户端应用程序使用的范围(标准或自定义),注意openid
和offline_acces 范围不需要明确的权限。
以下示例中,angular客户端允许请求address
, profile
和marketing_api
范围:任何其他范围都将导致返回错误。
if (await manager.FindByClientIdAsync("angular") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "angular", DisplayName = "Angular", RedirectUris = { new Uri("https://localhost:34422/callback") }, Permissions = { OpenIddictConstants.Permissions.Endpoints.Authorization, OpenIddictConstants.Permissions.GrantTypes.Implicit, OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Profile, OpenIddictConstants.Permissions.Prefixes.Scope + "marketing_api" } }); }
如果不想使用范围权限,请调用options.IgnoreScopePermissions()
以忽略它们:
services.AddOpenIddict() .AddServer(options => { options.IgnoreScopePermissions(); });
2.4 响应类型权限
是指:限制客户端应用程序在实现交互式流(如代码、隐式或混合)时允许使用的响应类型。
响应类型 | 枚举类型 |
code | OpenIddictConstants.Permissions.ResponseTypes.Code |
code id_token | OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken |
code id_token token | OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken |
code token | OpenIddictConstants.Permissions.ResponseTypes.CodeToken |
id_token | OpenIddictConstants.Permissions.ResponseTypes.IdToken |
id_token token | OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken |
none | OpenIddictConstants.Permissions.ResponseTypes.None |
token | OpenIddictConstants.Permissions.ResponseTypes.Token |
下面示例中,postman客户端只使用code id_token响应类型
if (await manager.FindByClientIdAsync("postman") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "postman", DisplayName = "Postman", RedirectUris = { new Uri("https://www.getpostman.com/oauth2/callback") }, Permissions = { OpenIddictConstants.Permissions.Endpoints.Authorization, OpenIddictConstants.Permissions.Endpoints.Token, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken } }); }
如果不想使用响应类型权限,请调用options.IgnoreResponseTypePermissions()
以忽略它们:
services.AddOpenIddict() .AddServer(options => { options.IgnoreResponseTypePermissions(); });