Description
阮一峰: http://www.ruanyifeng.com/blog/2019/04/github-oauth.html
OAuth2简明手册: https://aaronparecki.com/oauth-2-simplified
极简: http://tutorials.jenkov.com/oauth2/index.html
我对Authorization Code认证方式的思考
有同事报怨OAuth2中的access code没法重用, 我回头想了一下原因. 仔细推敲才发现OAuth2设计的是如此巧妙.
注: 以下文字中的developer和client均表示使用API的开发者(或APP).
1. 为什么要有authorization code认证方式?
- API需要保护, 最起码对调用次数和流量有所要求, 如果给匿名用户调用容易遭到恶意攻击. 所以首先需要client key和client secret(由API Provider给developer一个用户和口令, 用来分辨API是哪个client调用的), 算是对developer的一个认证过程.
- API中的敏感数据(比如账户余额)是Customer的, 如果App需要查看, 是需要Customer同意的. 于是customer也有自己的用户名和密码. 但是Customer不可能把自己的密码给developer, 谨慎的Customer也不会在developer开发的app/client上输入用户名密码, 于是有了认证服务器.
- 认证服务器必须是Customer信任的, 银行自己的产品比如官网是Customer唯一的选择.
- 为了调用到实际的API, 基于以上安全性的考虑, 对Developer的认证和对Customer的认证都必不可少.
授权码模式
: Authorization Code方式就是这样一个两步认证的过程.
2. 为什么需要两步 ?
不能一步得到token吗? 前面说了, 调用API需要提供两组用户名和密码才足够安全.
要是一步就能可以得到token, 那得一下传两个用户名和密码, 传给谁??? Customer只相信银行官网(不会把密码给API Provider) Developer只信任API Provider(不会把密码给银行官网).
所以需要两步: 1) Customer银行页面输入密码后得到access code
, 这个access code通过URL传给developer. 2) Developer再通过access code还有自己的密码 交换到一个 access token
.
3. 为什么access code不能重用?
首先code是暴露在浏览器URL中的, 非常不安全. 所以可以想像它是一个兑换码, 用一次就作废. 这个code会第一时间通过URL 传给developer, developer通常也是第一时间用它来交换token. 即使其它developer通过窥屏/录像/抓图得到这个code也无法使用.
4. 为什么token可以重用?
- Token通过response body并且是https的方式传给developer, 不像code那样容易暴露.
- Token发送给了server(比如nodejs), 并不会发给browser, 用户很难获取.
- Token完全由Developer和API Provider控制, 一旦泄漏可以随时召回
- Token都设置了有效时间, 一段时间即失效.
- 得到Token的过程只需一次, developer可以把这个token放在session里, 重复使用.
99%
的时间都是使用token调用API.. 只传一个token就可以调用API一是比较方便, 二是token中即没有Developer的密码信息也没有Customer的密码信息, (相对其它的认证方式比如Basic来说更加安全).
其它的方式
密码模式
: 如果Customer完全信任Developer, 愿意把账户密码交给developer, 那么可以使用password的方式由Developer一下传4个参数一步得到token客户端模式
: 如果API没有什么敏感信息, 可以使用Client Credentials
的方式, 也是一次得到Token, 只需要传Developer自己的用户名(Client key)和密码(client secret).简化模式
: Implicit 和 Access Code方式一样, 只不过是认证服务器通过redirect_url一步返回access_token给client, 这种方式不需要client_secret. 用在纯js客户端(就是client不像我做的是 个nodejs的程序), 不会有session, 然后你想如果client_secret直接从browser传到Authentication Server那么. 用户在浏览器上中就能看到client secret, 不太安全, 所以干脆只做customer authentication不做client authentication, 见: What is the purpose of the implicit grant authorization type in OAuth 2?
References
见理解OAuth 2.0: http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
一共有4种授权模式, implicit, client_credentials(application), password和authorization code. password是两腿模式(2-legged oauth, 需要server和client参与), 其它都是三腿模式(需要server, client和user三方参与)
和IBM API Connect的整合见我的另一篇总结 #179
Fundamental to the power of OAuth is the notion of delegation. Although OAuth is often called an authorization protocol (and this is the name given to it in the RFC which defines it), it is a delegation protocol. Generally, a subset of a user’s authorization is delegated, but OAuth itself doesn’t carry or convey the authorizations. Instead, it provides a means by which a client can request that a user delegate some of their authority to it. The user can then approve this request, and the client can then act on it with the results of that approval.
In our printing example, the photo-printing service can ask the user, “Do you have any of your photos stored on this storage site? If so, we can totally print that.” The user is then sent to the photo-storage service, which asks, “This printing service is asking to get some of your photos; do you want that to happen?” The user can then decide whether they want that to happen, deciding whether to delegate access to the printing service.
The distinction between a delegation and an authorization protocol is important here because the authorizations being carried by the OAuth token are opaque to most of the system. Only the protected resource needs to know the authorization, and as long as it’s able to find out from the token and its presentation context (either by look- ing at the token directly or by using a service of some type to obtain this information), it can serve the API as required.
https://my.oschina.net/liuyatao19921025/blog/1605948
https://developer.ibm.com/apiconnect/2017/04/11/securing-apis-using-oauth-in-apiconnect/
https://ibm-apiconnect.github.io/pot/lab3_oauth_api.html