推送授权请求(PAR)是一项新的OAuth 2.0功能,允许客户端通过直接请求将OAuth 2.0授权请求的有效载荷推向授权服务器,并为他们提供了用作对数据的参考的请求URI在随后的授权端点的请求中。此功能在
https://tools.ietf.org/html/rfc9156中定义。
Authorization Code Flow
让我们看一下当前ABP框架应用程序中的授权码流。
一个典型的ABP分层架构通常包含以下几个网站:
Acme.AuthServer: 集成OpenIddict的OAuth2.0认证服务器. Acme.AuthServer.Api.Host: API网站,它使用JWT bearer认证方案并通过Acme.AuthServer网站进行身份认证。 Acme.Web: 配置和启用OpenID Connect认证方案从Acme.AuthServer网站进行身份认证。
当我们在 Acme.Web
网站尝试使用OpenID Connect
认证时,它会构建一个认证请求并在浏览器中重定向到Acme.AuthServer
网站。
GET https//auth-server.acme.com/connect/authorize
Query String Parameters:
client_id: AbpApp
redirect_uri: https://web.acme.com/signin-oidc
response_type: code
scope: openid profile email roles phone AbpAPI
response_mode: form_post
nonce: YzVkMj...
state: CfDJ8N...
如果你启用了
Pkce
,那么code_challenge
和code_challenge_method
参数也会出现在请求中。
code_challenge: mJxMdU...
code_challenge_method: S256
当用户在Acme.AuthServer
网站中进行认证后(如用户名和密码或者社交登录),它会在用户同意授权后(consent screen/page
)会返回一个code
给Acme.Web
网站.
Acme.AuthServer
网站将构建一个POST
请求或者GET
请求到Acme.Web
网站。
POST https://web.acme.com/signin-oidc
Form Data Parameters(application/x-www-form-urlencoded):
code: LPjZ6C...
state: state: CfDJ8N...
iss: https://auth-server.acme.com/
当Acme.Web
网站收到code
后,它会在应用中(不是浏览器中)发送一个HTTP请求使用获得的code
向Acme.AuthServer
请求access token
。
POST https://auth-server.acme.com/connect/token
Form Data Parameters(application/x-www-form-urlencoded):
client_id: AbpApp
client_secret: secret
code: LPjZ6C...
grant_type: authorization_code
到此为止,完成了授权码流的认证流程, 之后我们就可以使用access token
来访问Acme.AuthServer.Api.Host
网站的API了。
混合流程(Hybrid Flow)与隐式流程(Implicit Flow)和授权码流(Code Flow)类似。我们只讨论授权码流
不过授权码流可能有以下问题:
授权请求可以被修改。通常,客户端应用会将用户的浏览器重定向到授权服务器,并附上授权 URL。没有任何机制可以阻止恶意行为者在将请求发送到授权服务器之前,修改其中的一个或多个参数。 无法保证请求的来源。授权请求通常由客户端应用构建,用户的浏览器负责将其发送到授权服务器。然而,无法保证请求确实是由客户端应用构建的。任何人在知道一些数据(如客户端 ID 和重定向 URI)后,都可以构建一个授权请求。 无法保证机密性。尽管浏览器通过 HTTPS 发送授权请求,但请求参数可能会被第三方应用程序拦截,如代理、负载均衡器,甚至是浏览器插件。这类恶意网络组件可以注入或更改请求参数,更不用说请求本身可能会被记录下来。 浏览器的限制。最后,授权请求中的查询字符串如果过于复杂,可能会遇到浏览器对 URL 长度的限制。
为了解决这些问题,OAuth 2.0
定义了Pushed Authorization Requests (PAR)
。
Pushed Authorization Requests (PAR)
OpenIdDict 6.1.0 版本开始支持Pushed Authorization Requests (PAR)。ABP框架第一时间升级OpenIdDict
版本(9.2版本可用),并在Volo.OpenIddict.Pro模块中添加了Pushed Authorization Requests (PAR)的配置.
你可以在创建/更新Application
的时候配置Pushed Authorization Requests (PAR)
。
我们在看看使用Pushed Authorization Requests (PAR)
的认证流程。
当我们在Acme.Web
网站尝试使用OpenID Connect
认证时它会在会在应用中(不是浏览器中)发送一个POST
请求到授权服务器的par
端点。
POST https://auth-server.acme.com/connect/par
Form Data Parameters:
client_id: AbpApp
client_secret: secret
redirect_uri: https://web.acme.com/signin-oidc
response_type: code
scope: openid profile email roles phone AbpAPI
response_mode: form_post
nonce: YzVkMjZmN...
state: CfDJ8NwA4...
如果你启用了
Pkce
,那么code_challenge
和code_challenge_method
参数也会出现在POST
请求中。
code_challenge: mJxMdU...
code_challenge_method: S256
授权服务器检查和验证成功后会返回request_uri
给Acme.Web
应用。
{
"request_uri": "urn:ietf:params:oauth:request_uri:1FPVWn...",
"expires_in": 3599
}
Acme.Web网站收到成功响应后会构建一个授权请求,并在浏览器中重定向到授权服务器。
GET https//auth-server.acme.com/connect/authorize
Query String Parameters:
client_id: AbpApp
request_uri: urn:ietf:params:oauth:request_uri:1FPVWn...
同样, 当用户在Acme.
AuthServer
网站中通过授权后会返回一个code
给Acme.Web
网站, 然后就可以继续使用code
请求access token
了, 和上述的授权码流一样.
在应用中配置并启用PAR
ABP的OpenIddict模块默认启用了PAR
特性.
ASP NET Core 9.0 中 OpenIdConnect 认证方案的OpenIdConnectOptions中增加了一个新的
PushedAuthorizationBehavior参数,你可以在你的应用中配置它.
AddAbpOpenIdConnect("oidc", options =>
{
//...
options.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Require;
//...
});
并非全部的认证客户端都支持
PAR
,比如Blazor WASM
还不支持。
总结
Pushed Authorization R
eques
ts (PAR)
是一种新的 OAuth 2.0
功能,它增强了授权码流的健壮性。我们推荐你在你的应用中使用它.
参考
Volo.OpenIddict.Pro模块 https://abp.io/modules/Volo.OpenIddict.Pro What Are OAuth Pushed Authorization Requests (PAR)? https://auth0.com/blog/what-are-oauth-push-authorization-requests-par/ OpenIddict Pushed Authorization Requests (PAR) https://documentation.openiddict.com/configuration/pushed-authorization-requests Support for Pushed Authorization (PAR) in OIDC Handler https://github.com/dotnet/aspnetcore/pull/55069 RFC 9156 https://tools.ietf.org/html/rfc9156